{"openapi":"3.1.0","info":{"title":"The Vibe Hosting — control plane","version":"1.0.0"},"paths":{"/create":{"post":{"summary":"Create a server","description":"Create a root Linux server on an HTTPS subdomain. **No body required** — a bare\ncall makes an anonymous server on a random subdomain and returns an `api_key`.\n\nAuth: send `Authorization: Bearer <api_key>` to create under an existing account;\nomit it on the first call (an account is created and its `api_key` returned).\n\nAll body fields are optional: `subdomains`/`subdomain` (pick the URL), `never_sleep`\n(keep it always running, verified-only), and `phone`/`code` (sign up or log into\na verified account in one flow — no IP limit). See the field docs.\n\nLimits: anonymous accounts are capped per creator IP; verified accounts are\nunlimited. Returns SSH details, the live subdomain, and the account `api_key`.","operationId":"create_server_create_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/CreateServerReq"},{"type":"null"}],"title":"Req"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateServerResp"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account":{"get":{"summary":"Whoami","operationId":"whoami_account_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account/billing":{"get":{"summary":"Account Billing","description":"Usage-based billing snapshot (VH-21): the two credit buckets, the monthly free\nfloor + when it renews, the rates, your current RAM ceiling, and your live burn rate.","operationId":"account_billing_account_billing_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account/usage":{"get":{"summary":"Account Usage","description":"Hourly consumption history (VH-21) — one row per server per hour, newest first.\nusd_charged is everything billed that hour (RAM + egress + disk); disk_usd is the disk\npart — disk is billed around the clock, so sleeping servers have rows too.","operationId":"account_usage_account_usage_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/servers":{"get":{"summary":"List Servers","operationId":"list_servers_servers_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/servers/{server_id}":{"get":{"summary":"Get Server","operationId":"get_server_servers__server_id__get","parameters":[{"name":"server_id","in":"path","required":true,"schema":{"type":"string","title":"Server Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Server","operationId":"delete_server_servers__server_id__delete","parameters":[{"name":"server_id","in":"path","required":true,"schema":{"type":"string","title":"Server Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/servers/{server_id}/ssh":{"get":{"summary":"Get Ssh","description":"SSH login info for a server. *Auth required.* Returns the connection command\n(host/port/user=root). The private key is shown ONLY once at create and is not\nstored — use the key you saved (`ssh -i <key> -o IdentitiesOnly=yes …`).\nConnecting also wakes a sleeping server. To use a new key, append it with\nPOST /servers/{id}/ssh-key.","operationId":"get_ssh_servers__server_id__ssh_get","parameters":[{"name":"server_id","in":"path","required":true,"schema":{"type":"string","title":"Server Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/servers/{server_id}/usage":{"get":{"summary":"Get Usage","operationId":"get_usage_servers__server_id__usage_get","parameters":[{"name":"server_id","in":"path","required":true,"schema":{"type":"string","title":"Server Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/servers/{server_id}/subdomain":{"post":{"summary":"Set Subdomain","operationId":"set_subdomain_servers__server_id__subdomain_post","parameters":[{"name":"server_id","in":"path","required":true,"schema":{"type":"string","title":"Server Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubdomainReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/servers/{server_id}/domain":{"post":{"summary":"Add Domain","description":"VH-8: attach a custom domain (transparent serve — the app runs FROM the domain).\nSelf-describing: returns the exact DNS records to set + how to re-check. Verified\naccounts only (phone-verified; everyone during beta).","operationId":"add_domain_servers__server_id__domain_post","parameters":[{"name":"server_id","in":"path","required":true,"schema":{"type":"string","title":"Server Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"List Domains","description":"List a server's custom domains with live status + the records to set. Re-runs the\nDNS check, so polling this flips a domain pending→live once it points at our edge.","operationId":"list_domains_servers__server_id__domain_get","parameters":[{"name":"server_id","in":"path","required":true,"schema":{"type":"string","title":"Server Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Remove Domain","description":"Detach a custom domain. The container is relabeled (recreate) so it no longer\nanswers on that host, and it drops from the edge route map on the next poll.","operationId":"remove_domain_servers__server_id__domain_delete","parameters":[{"name":"server_id","in":"path","required":true,"schema":{"type":"string","title":"Server Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/servers/{server_id}/expose":{"post":{"summary":"Expose","operationId":"expose_servers__server_id__expose_post","parameters":[{"name":"server_id","in":"path","required":true,"schema":{"type":"string","title":"Server Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExposeReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/servers/{server_id}/ssh-key":{"post":{"summary":"Add Ssh Key","description":"Add another SSH public key for root — e.g. you lost the key from create, or want a\nsecond machine to log in. Works whether the server is running or asleep, takes\neffect on the next login and survives restarts. Keys you add are stored in\n/root/.ssh/authorized_keys2 (the create-time key stays in authorized_keys).","operationId":"add_ssh_key_servers__server_id__ssh_key_post","parameters":[{"name":"server_id","in":"path","required":true,"schema":{"type":"string","title":"Server Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SshKeyReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/servers/{server_id}/refresh-ram":{"post":{"summary":"Refresh Ram","description":"Apply your account's currently-entitled RAM ceiling to this server (VH-21): the\ntier ceiling, boosted to the with-credit ceiling while you hold paid credit ≥ $1.\nUse it after topping up to claim the bigger box, or to drop back down. Data is\npreserved — a running server gets a brief restart (SSH drops, reconnect).","operationId":"refresh_ram_servers__server_id__refresh_ram_post","parameters":[{"name":"server_id","in":"path","required":true,"schema":{"type":"string","title":"Server Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/servers/{server_id}/never-sleep":{"post":{"summary":"Set Never Sleep","description":"Turn always-on (`never_sleep`) on or off for an EXISTING server — the same flag you\ncan pass to POST /create. On: it never scales to zero (no cold starts), billed by real\nRAM 24/7 from your credit; a sleeping server is woken right away. Off: it goes back to\nscale-to-zero and sleeps after the idle timeout. Turning it ON needs a verified phone.\nNo restart either way — nothing is lost.","operationId":"set_never_sleep_servers__server_id__never_sleep_post","parameters":[{"name":"server_id","in":"path","required":true,"schema":{"type":"string","title":"Server Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NeverSleepReq","default":{"never_sleep":true}}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/servers/{server_id}/sleep":{"post":{"summary":"Sleep Server","description":"Manually scale to zero now — stop the container, free RAM, pause RAM billing.\nWakes again on the next HTTP request / SSH connection, or POST .../wake.","operationId":"sleep_server_servers__server_id__sleep_post","parameters":[{"name":"server_id","in":"path","required":true,"schema":{"type":"string","title":"Server Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/servers/{server_id}/wake":{"post":{"summary":"Wake Server","description":"Manually start a sleeping server (pre-warm). Blocks briefly until the app\nbinds :80 so the caller knows it's ready; non-HTTP servers just report started.","operationId":"wake_server_servers__server_id__wake_post","parameters":[{"name":"server_id","in":"path","required":true,"schema":{"type":"string","title":"Server Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account/verify-phone":{"post":{"summary":"Verify Phone","operationId":"verify_phone_account_verify_phone_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyPhoneReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account/recover":{"post":{"summary":"Recover Account","description":"Recover a lost api_key by re-verifying the phone already on the account.\nStep 1 {phone} → SMS code. Step 2 {phone, code} → returns the api_key.\nVH-SEC-3: validate + rate-limit; send only to registered numbers; respond\ngenerically so the endpoint can't be used to enumerate accounts or SMS-bomb.","operationId":"recover_account_account_recover_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyPhoneReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account/topup":{"post":{"summary":"Topup","operationId":"topup_account_topup_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/TopupReq"},{"type":"null"}],"title":"Req"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/account/recharge":{"post":{"summary":"Topup","operationId":"topup_account_recharge_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/TopupReq"},{"type":"null"}],"title":"Req"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/abuse":{"post":{"summary":"Report abuse","description":"Report a server hosted here that is doing harm (phishing, malware, scanning …).\nNo account needed. Reports go straight to the operator.","operationId":"report_abuse_abuse_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AbuseReportReq"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/feedback":{"post":{"summary":"Feedback","operationId":"feedback_feedback_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackReq"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AbuseReportReq":{"properties":{"target":{"type":"string","maxLength":500,"minLength":1,"title":"Target","description":"The URL or host of the server you're reporting."},"category":{"type":"string","enum":["phishing","malware","spam","scanning","ddos","fraud","illegal_content","copyright","other"],"title":"Category","default":"other"},"description":{"type":"string","maxLength":4000,"title":"Description","default":""},"email":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Email","description":"Optional — if you'd like us to follow up."}},"type":"object","required":["target"],"title":"AbuseReportReq"},"CreateServerReq":{"properties":{"subdomains":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Subdomains","description":"Preference-ordered list of desired subdomain slugs; the first available one is taken (include a couple of fallbacks). Lowercased; letters/digits/hyphens, 3–32 chars; reserved/brand labels skipped. Omit for a random slug. If none are usable/free a random slug is used and subdomain_note explains it.","examples":[["caffeine-tracker","caffeine-app"]]},"never_sleep":{"type":"boolean","title":"Never Sleep","description":"Keep this server always running — never auto-scale-to-zero (no cold starts). Billed by real RAM usage 24/7 from your credit, same rate as any awake server. Requires a verified phone.","default":false},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone","description":"Sign up / log in with a phone (E.164, e.g. +420777123456) to land the server on a VERIFIED account (no IP limit, unlimited servers). Two steps: send {phone, consent:true} → SMS code; resend the same body + {code}. If the number already has an account you're logged into it (its api_key is returned). The code is required.","examples":["+420777123456"]},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code","description":"The SMS code, to finish phone signup/login. Send with `phone` (+ the same body as the first call)."}},"type":"object","title":"CreateServerReq","description":"Body for POST /create — every field is optional. With no body you get an\nanonymous server on a random subdomain."},"CreateServerResp":{"properties":{"id":{"type":"string","title":"Id"},"ssh":{"type":"string","title":"Ssh"},"ssh_private_key":{"type":"string","title":"Ssh Private Key"},"ssh_private_key_b64":{"type":"string","title":"Ssh Private Key B64","default":""},"save_ssh_key":{"additionalProperties":true,"type":"object","title":"Save Ssh Key","default":{}},"subdomain":{"type":"string","title":"Subdomain"},"subdomain_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subdomain Note"},"api_key":{"type":"string","title":"Api Key"},"account_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Note"},"credits":{"$ref":"#/components/schemas/Credits"},"ONBOARDING":{"type":"string","title":"Onboarding"}},"type":"object","required":["id","ssh","ssh_private_key","subdomain","api_key","credits","ONBOARDING"],"title":"CreateServerResp"},"Credits":{"properties":{"tier":{"type":"string","title":"Tier"},"free_balance_usd":{"type":"number","title":"Free Balance Usd"},"paid_balance_usd":{"type":"number","title":"Paid Balance Usd","default":0.0},"total_usd":{"type":"number","title":"Total Usd"},"free_credits_monthly":{"type":"number","title":"Free Credits Monthly"}},"type":"object","required":["tier","free_balance_usd","total_usd","free_credits_monthly"],"title":"Credits","description":"The account's credit in dollars (VH-21) — the same numbers GET /account/billing\nshows. (Used to be a GB-hour grant, which read as \"$0 balance\" on a fresh account.)"},"DomainReq":{"properties":{"domain":{"type":"string","title":"Domain"}},"type":"object","required":["domain"],"title":"DomainReq"},"ExposeReq":{"properties":{"container_port":{"type":"integer","title":"Container Port"},"protocol":{"type":"string","enum":["tcp","udp"],"title":"Protocol","default":"tcp"}},"type":"object","required":["container_port"],"title":"ExposeReq"},"FeedbackReq":{"properties":{"kind":{"type":"string","enum":["feature","bug","friction","limit","image_request","other"],"title":"Kind"},"message":{"type":"string","title":"Message"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"context":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Context"}},"type":"object","required":["kind","message"],"title":"FeedbackReq"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"NeverSleepReq":{"properties":{"never_sleep":{"type":"boolean","title":"Never Sleep","description":"true = keep this server always running (never auto-scale-to-zero, no cold starts), billed by real RAM 24/7. false = let it sleep when idle. Turning it ON requires a verified phone.","default":true}},"type":"object","title":"NeverSleepReq"},"SshKeyReq":{"properties":{"public_key":{"type":"string","title":"Public Key"}},"type":"object","required":["public_key"],"title":"SshKeyReq"},"SubdomainReq":{"properties":{"subdomain":{"type":"string","title":"Subdomain"}},"type":"object","required":["subdomain"],"title":"SubdomainReq"},"TopupReq":{"properties":{"amount_usd":{"type":"number","title":"Amount Usd","default":5.0}},"type":"object","title":"TopupReq"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VerifyPhoneReq":{"properties":{"phone":{"type":"string","title":"Phone"},"consent":{"type":"boolean","title":"Consent","default":false},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"}},"type":"object","required":["phone"],"title":"VerifyPhoneReq"}}}}