{"components":{"responses":{},"schemas":{"TldRequirements":{"description":"One TLD's catalog entry plus what a registration of it must carry: `registration_schema` for the TLD-specific part of the POST /domains body, `registrant_schema` for the fields the registrant contact needs.","properties":{"categories":{"items":{"type":"string"},"type":"array"},"eligibility":{"description":"Who may register a name on this extension.","properties":{"policy":{"description":"The registry's eligibility policy, when it publishes one.","type":"string"},"restricted":{"description":"true when the registry limits who may register: a community or profession, or a connection to a place. Every requires_nexus TLD is restricted, and registrant_schema says what its registrant contact must carry. false: anyone may.","type":"boolean"},"summary":{"description":"Who qualifies, when restricted.","type":"string"}},"required":["restricted"],"type":"object"},"https_required":{"description":"true when browsers load websites on this extension over HTTPS only, because the whole extension is on the HSTS preload list (.app, .dev, .page and others): a site needs a valid TLS certificate before it loads, and http:// links are upgraded. Email and other non-web services are unaffected.","type":"boolean"},"icann_fee":{"description":"Per-year ICANN fee, added on top of each price; \"0.00\" on a ccTLD, which owes none. check_domain reports the same amount.","type":"string"},"max_years":{"type":"integer"},"min_years":{"type":"integer"},"name":{"nullable":true,"type":"string"},"period_years":{"description":"The term each price covers: always 1, so every price is per year. A purchase costs it times its years (at least min_years).","example":1,"type":"integer"},"premium_possible":{"description":"Whether the registry can price a name above these standard prices; when true, check_domain quotes the name.","type":"boolean"},"registrant_schema":{"additionalProperties":true,"description":"A JSON Schema (2020-12); {} when the TLD adds no requirement.","type":"object"},"registration":{"description":"Per-year retail price in the catalog's currency, as a decimal string.","nullable":true,"type":"string"},"registration_schema":{"additionalProperties":true,"description":"A JSON Schema (2020-12); {} when the TLD adds no requirement.","type":"object"},"renewal":{"description":"Per-year retail price in the catalog's currency, as a decimal string.","nullable":true,"type":"string"},"requires_nexus":{"type":"boolean"},"restore":{"description":"Per-year retail price in the catalog's currency, as a decimal string.","nullable":true,"type":"string"},"tld":{"example":"com","type":"string"},"transfer":{"description":"Per-year retail price in the catalog's currency, as a decimal string.","nullable":true,"type":"string"},"transfer_years":{"description":"Years a transfer in buys and is charged for, added to the expiry date. A transfer request takes no years: it's always this.","type":"integer"},"transfer_years_fixed":{"description":"true when the registry accepts exactly transfer_years on a transfer and no other period (PIR's .org: 1); false when transfer_years is this extension's shortest term (min_years).","type":"boolean"},"url":{"format":"uri","type":"string"},"whois_privacy":{"properties":{"price":{"type":"string"},"supported":{"type":"boolean"}},"required":["supported"],"type":"object"}},"required":["tld","name","registration","renewal","transfer","restore","icann_fee","period_years","min_years","max_years","transfer_years","transfer_years_fixed","requires_nexus","premium_possible","https_required","whois_privacy","eligibility","categories","url","registration_schema","registrant_schema"],"title":"TldRequirements","type":"object"},"WatchlistInput":{"additionalProperties":false,"properties":{"domain_name":{"example":"example.com","maxLength":253,"type":"string"},"intent":{"default":"save","description":"Adding a saved name again with notify turns notification on; a notify watch is never turned back into save.","enum":["save","notify"],"type":"string"}},"required":["domain_name"],"title":"WatchlistInput","type":"object"},"PurchaseRegistrant":{"description":"Who will legally own the domain a registration buys: the contact_id sent, else the account's default registrant. Null for a renewal or transfer, or when the account has no contact yet (a placeholder is then created and needs real details).","nullable":true,"properties":{"contact_id":{"format":"uuid","type":"string"},"country_code":{"description":"ISO 3166-1 alpha-2.","nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"organization":{"nullable":true,"type":"string"}},"title":"PurchaseRegistrant","type":"object"},"DomainSettingsInput":{"additionalProperties":false,"minProperties":1,"properties":{"auto_renew":{"description":"Renew automatically before expiry. Needs the edit_auto_renew permission.","type":"boolean"},"auto_renew_days_before":{"description":"How many days before expiry auto-renewal runs. Needs edit_auto_renew.","enum":[7,14,30,60,90],"type":"integer"},"auto_renew_max_price":{"description":"The most one year of auto-renewal may cost, in USD, ICANN fee included; null is no limit. Over it, auto-renewal neither renews nor charges. One of the values the domain page offers. Needs edit_auto_renew.","enum":["25.00","50.00","75.00","100.00","200.00","500.00",null],"nullable":true,"type":"string"},"auto_renew_years":{"description":"Years each auto-renewal buys: at least the TLD's minimum term, at most 9 (a renewal can't leave more than 10 years on the registration). Needs edit_auto_renew.","maximum":9,"minimum":1,"type":"integer"},"privacy":{"description":"WHOIS/RDAP privacy. Needs the edit_privacy permission; some TLDs (.us) forbid it (privacy_not_available).","type":"boolean"}},"title":"DomainSettingsInput","type":"object"},"DnsRecordCreateInput":{"description":"Request body for creating a DNS record.","properties":{"enabled":{"description":"Defaults to true. false marks the record as switched off in the DNS editor, but it is still published and answered: delete the record to take it out of DNS.","type":"boolean"},"name":{"description":"Record name: @ for the domain itself, or a subdomain such as www. A CNAME must be the only record at its name, and an ALIAS can't share a name with an A or AAAA.","example":"www","type":"string"},"priority":{"description":"For MX/SRV records","type":"integer"},"ttl":{"description":"Time to live, in seconds (default 3600).","example":3600,"type":"integer"},"type":{"description":"A, AAAA, ALIAS, CNAME, MX, TXT, NS, SRV, CAA or WR. ALIAS points a name at a hostname and answers with its addresses, which is how @ points at a hostname (a CNAME can't be at @). WR is a web redirect: value is an http:// or https:// URL, and web requests for the name get a 301 redirect to it. WR needs OrbitFour's DNS: a domain whose DNS is on Cloudflare can't use it.","example":"A","type":"string"},"value":{"description":"An IPv4 address (A), IPv6 address (AAAA), hostname (ALIAS, CNAME, MX, NS), any text (TXT), \"priority weight port target\" (SRV), \"flags tag value\" (CAA) or a URL (WR).","example":"203.0.113.4","type":"string"}},"required":["name","type","value"],"title":"DnsRecordCreateInput","type":"object"},"DomainCheckError":{"description":"A GET /domains/check entry for a name that could not be evaluated: malformed, or an unsupported TLD.","properties":{"error":{"example":"invalid_name","type":"string"},"name":{"example":"not a domain","type":"string"}},"required":["name","error"],"title":"DomainCheckError","type":"object"},"TransferInput":{"additionalProperties":false,"description":"Inbound transfer. The term is fixed by registry policy per TLD (not client-selectable). WHOIS privacy is enabled and the domain's current nameservers are kept; change either after the transfer completes.","properties":{"auth_code":{"description":"Transfer authorization (EPP) code from the current registrar.","type":"string"},"domain_name":{"example":"example.com","type":"string"},"dry_run":{"description":"true: answer 200 with a PurchaseQuote (the total, how it would pay, a quote_token) and charge nothing.","nullable":true,"type":"boolean"},"max_price":{"description":"Optional ceiling on this operation's full charge, as a USD decimal string: every year and the ICANN fee included, the same figure the response reports as amount. A higher charge is refused with 422 max_price_exceeded, which reports the price, and nothing is charged.","example":"50.00","nullable":true,"type":"string"},"payment_method":{"description":"\"balance\" forces the prepaid balance (402 if insufficient, no fallback); omit for balance-first with default-card fallback; \"default\", a payment-method UUID, or a last-four selects a card. An ambiguous last-four returns 409 with candidate ids.","example":"balance","nullable":true,"type":"string"},"quote_token":{"description":"From a dry run of this same operation, at most 10 minutes old. The purchase must match it; a higher live price is refused with quote_changed (and a fresh quote); a token is spent once, and sending it again returns the first operation.","nullable":true,"type":"string"}},"required":["domain_name","auth_code"],"title":"TransferInput","type":"object"},"MeAccountList":{"description":"The accounts the caller can act in. An app sends one id as X-OrbitFour-Account.","properties":{"data":{"items":{"properties":{"id":{"format":"uuid","type":"string"},"name":{"type":"string"},"role":{"description":"owner, admin, member or viewer","example":"owner","type":"string"},"slug":{"type":"string"},"status":{"example":"active","type":"string"}},"required":["id","name","slug","status","role"],"type":"object"},"type":"array"}},"required":["data"],"title":"MeAccountList","type":"object"},"DomainQuote":{"description":"One name's availability and per-year price, shared by GET /domains/check and GET /domains/search. `rank`, `hack` and `match` appear on search suggestions only; `reason` only when the name isn't available.","properties":{"available":{"description":"null when the registry could not be asked (degraded availability).","nullable":true,"type":"boolean"},"currency":{"example":"USD","type":"string"},"first_term":{"description":"Available names: the shortest term the request allows (years or min_years) and its total, the ICANN fee included. A purchase's max_price taken from it always covers it.","nullable":true,"properties":{"total":{"$ref":"#/components/schemas/Money"},"years":{"type":"integer"}},"required":["years","total"],"type":"object"},"hack":{"description":"True when the name is a domain hack, e.g. danger.zone (search only).","type":"boolean"},"icann_fee":{"$ref":"#/components/schemas/NullableMoney"},"match":{"description":"exact_sld: the SLD as searched; variation: a stem or a hack (search only).","enum":["exact_sld","variation"],"type":"string"},"min_years":{"description":"Smallest purchase term; prices are per year.","type":"integer"},"name":{"example":"example.com","type":"string"},"premium":{"type":"boolean"},"pricing_source":{"description":"registry: priced live for this name. baseline: the extension's standard rate, and final for this name: the extension has no premium names (premium_possible is false in GET /pricing/{tld}), or the registry's live check returned no premium price for it. unconfirmed: the registry lookup didn't finish, so on an extension with premium names the price isn't final. A purchase checks the price again either way. Describes REGISTRATION only; see pricing_sources for the others.","enum":["registry","baseline","unconfirmed"],"type":"string"},"pricing_sources":{"properties":{"registration":{"description":"registry: priced live for this name. baseline: the extension's standard rate, and final for this name: the extension has no premium names (premium_possible is false in GET /pricing/{tld}), or the registry's live check returned no premium price for it. unconfirmed: the registry lookup didn't finish, so on an extension with premium names the price isn't final. A purchase checks the price again either way.","enum":["registry","baseline","unconfirmed"],"type":"string"},"renewal":{"description":"registry: priced live for this name. baseline: the extension's standard rate, and final for this name: the extension has no premium names (premium_possible is false in GET /pricing/{tld}), or the registry's live check returned no premium price for it. unconfirmed: the registry lookup didn't finish, so on an extension with premium names the price isn't final. A purchase checks the price again either way.","enum":["registry","baseline","unconfirmed"],"type":"string"},"transfer":{"description":"registry: priced live for this name. baseline: the extension's standard rate, and final for this name: the extension has no premium names (premium_possible is false in GET /pricing/{tld}), or the registry's live check returned no premium price for it. unconfirmed: the registry lookup didn't finish, so on an extension with premium names the price isn't final. A purchase checks the price again either way.","enum":["registry","baseline","unconfirmed"],"type":"string"}},"required":["registration","renewal","transfer"],"type":"object"},"purchasable":{"description":"Available and buyable here now; a purchase still re-checks.","type":"boolean"},"purchase_blocker":{"description":"Why a name isn't purchasable: premium_over_cap (a premium above the $10,000 cap), price_unconfirmed (the registry didn't confirm the price), availability_unknown (available is null: the registry couldn't be asked, so check again). null when purchasable, and when available is false, where reason says why.","enum":["premium_over_cap","price_unconfirmed","availability_unknown",null],"nullable":true,"type":"string"},"rank":{"description":"1-based relevance ordinal (search only).","type":"integer"},"reason":{"description":"Only when available is false or null. unavailable: the registry won't offer it (or said why in words we don't map); unknown: the check failed or was shed, so try again. This set won't grow.","enum":["taken","reserved","unavailable","unknown"],"type":"string"},"registration":{"$ref":"#/components/schemas/Money"},"renewal":{"$ref":"#/components/schemas/NullableMoney"},"transfer":{"$ref":"#/components/schemas/NullableMoney"}},"required":["name","available","premium","currency","registration","renewal","transfer","pricing_source","pricing_sources","min_years","purchasable","purchase_blocker","icann_fee","first_term"],"title":"DomainQuote","type":"object"},"Error":{"description":"Standard error envelope for the OrbitFour API.","properties":{"error":{"properties":{"code":{"description":"Machine-readable error code","example":"not_found","type":"string"},"details":{"additionalProperties":true,"description":"Optional structured details. Free-form: its keys depend on `code` (see the error catalog in /llms-full.txt).","type":"object"},"message":{"description":"Human-readable message","type":"string"}},"required":["code","message"],"type":"object"}},"required":["error"],"title":"Error","type":"object"},"NameserversInput":{"additionalProperties":false,"properties":{"nameservers":{"description":"The complete new set, replacing the current one. Use ns1.o4dns.com and ns2.o4dns.com for OrbitFour DNS.","items":{"example":"ns1.example.net","type":"string"},"maxItems":10,"minItems":1,"type":"array"}},"required":["nameservers"],"title":"NameserversInput","type":"object"},"DeviceInput":{"additionalProperties":false,"properties":{"apns_environment":{"default":"production","description":"sandbox for builds installed from Xcode; production for TestFlight and the App Store.","enum":["production","sandbox"],"type":"string"},"app_version":{"description":"Marketing version and build, e.g. 1.2.0+45.","maxLength":64,"type":"string"},"platform":{"default":"ios","enum":["ios"],"type":"string"},"token":{"description":"The APNs device token, hex.","pattern":"^[0-9a-fA-F]{64,200}$","type":"string"}},"required":["token"],"title":"DeviceInput","type":"object"},"TeamPermissions":{"additionalProperties":false,"description":"Granular permissions by name. On a member: what they may do now (role plus any switched off). On input: only permissions the role grants can be switched off with false; true for one the role doesn't grant is refused.","properties":{"edit_auto_renew":{"type":"boolean"},"edit_billing":{"type":"boolean"},"edit_dns":{"type":"boolean"},"edit_dnssec":{"type":"boolean"},"edit_nameservers":{"type":"boolean"},"edit_privacy":{"type":"boolean"},"edit_sites":{"type":"boolean"},"edit_tags":{"type":"boolean"},"register_domains":{"type":"boolean"},"transfer_in":{"type":"boolean"},"transfer_out":{"type":"boolean"},"update_contacts":{"type":"boolean"},"view_billing":{"type":"boolean"}},"title":"TeamPermissions","type":"object"},"Device":{"properties":{"apns_environment":{"type":"string"},"app_version":{"nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"last_registered_at":{"format":"date-time","type":"string"},"platform":{"type":"string"}},"required":["id","platform","apns_environment","last_registered_at"],"title":"Device","type":"object"},"WebhookEndpoint":{"properties":{"active":{"type":"boolean"},"consecutive_failures":{"type":"integer"},"created_at":{"format":"date-time","type":"string"},"description":{"nullable":true,"type":"string"},"disabled_reason":{"description":"Why it was switched off, when it was.","nullable":true,"type":"string"},"events":{"description":"Subscribed event types; [\"*\"] is all of them.","items":{"type":"string"},"type":"array"},"id":{"format":"uuid","type":"string"},"last_failure_at":{"format":"date-time","nullable":true,"type":"string"},"last_success_at":{"format":"date-time","nullable":true,"type":"string"},"secret":{"description":"The signing secret (whsec_…). Returned only when the endpoint is created and when its secret is rotated.","nullable":true,"type":"string"},"url":{"format":"uri","type":"string"}},"required":["id","url","events","active","consecutive_failures","created_at"],"title":"WebhookEndpoint","type":"object"},"Money":{"description":"An amount as a decimal string, never a float, with its ISO 4217 currency. Ledger amounts are signed.","properties":{"amount":{"example":"12.99","type":"string"},"currency":{"example":"USD","type":"string"}},"required":["amount","currency"],"title":"Money","type":"object"},"PaymentMethod":{"properties":{"brand":{"example":"Visa","nullable":true,"type":"string"},"exp_month":{"nullable":true,"type":"integer"},"exp_year":{"nullable":true,"type":"integer"},"id":{"format":"uuid","type":"string"},"is_default":{"type":"boolean"},"last4":{"example":"4242","nullable":true,"type":"string"},"nickname":{"nullable":true,"type":"string"},"type":{"example":"card","type":"string"}},"title":"PaymentMethod","type":"object"},"PaymentMethodUpdateInput":{"additionalProperties":false,"properties":{"is_default":{"description":"Only `true` is accepted: make this the default card. To move the default, set it on another card.","enum":[true],"type":"boolean"},"nickname":{"description":"A label for the card; null or \"\" clears it.","maxLength":60,"nullable":true,"type":"string"}},"title":"PaymentMethodUpdateInput","type":"object"},"DnsRecord":{"properties":{"created_at":{"format":"date-time","type":"string"},"enabled":{"description":"false only marks the record as switched off in the DNS editor: it is still published.","type":"boolean"},"id":{"format":"uuid","type":"string"},"name":{"example":"www","type":"string"},"priority":{"nullable":true,"type":"integer"},"ttl":{"description":"Time to live, in seconds.","example":3600,"type":"integer"},"type":{"example":"A","type":"string"},"updated_at":{"description":"When the record last changed here.","format":"date-time","type":"string"},"value":{"example":"203.0.113.4","type":"string"}},"title":"DnsRecord","type":"object"},"Operation":{"description":"An async paid domain operation (registration, renewal, or inbound transfer). Poll GET /api/v1/operations/{id} until status leaves \"processing\".","properties":{"amount":{"$ref":"#/components/schemas/Money"},"created_at":{"format":"date-time","type":"string"},"domain_id":{"description":"Set once the operation completes.","format":"uuid","nullable":true,"type":"string"},"domain_name":{"example":"example.com","type":"string"},"error":{"description":"Customer-safe fulfillment failure message, when failed.","nullable":true,"type":"string"},"error_code":{"description":"Stable machine-readable failure code to branch on. Null when `error` is set but the failure is unrecognized.","nullable":true,"type":"string"},"id":{"description":"The operation's billing transaction id: the transaction_id on its ledger entries and its id in GET /transactions.","format":"uuid","type":"string"},"is_premium":{"type":"boolean"},"operation":{"enum":["registration","renewal","transfer"],"type":"string"},"payment":{"description":"Only on the 202 of a client_confirm operation: what Stripe PaymentSheet needs to confirm it. Not repeated on GET; an unconfirmed operation is released after 30 minutes. Always null for a balance or saved-card purchase.","nullable":true,"properties":{"client_secret":{"type":"string"},"payment_intent_id":{"type":"string"},"publishable_key":{"nullable":true,"type":"string"}},"type":"object"},"payment_method":{"description":"Settlement path used.","enum":["balance","card"],"type":"string"},"refund":{"nullable":true,"properties":{"amount":{"$ref":"#/components/schemas/Money"},"reference":{"description":"Stripe refund id (card path); balance reversals have none.","nullable":true,"type":"string"},"refunded_at":{"format":"date-time","nullable":true,"type":"string"}},"type":"object"},"retry_after":{"description":"Suggested seconds before polling again, while in flight.","nullable":true,"type":"integer"},"status":{"description":"requires_payment: the app must confirm the payment (client_confirm); the 202 carries `payment.client_secret`. pending_payment: card authentication in flight. processing: paid, fulfillment running. completed: done (domain_id set). action_required: transfer held for a user-fixable issue (e.g. bad auth code) — resolve via the web UI. failed_refund_pending / failed_refunded: fulfillment failed, money coming back / returned. payment_failed: nothing charged.","enum":["requires_payment","pending_payment","processing","completed","action_required","failed_refund_pending","failed_refunded","payment_failed","canceled"],"type":"string"},"updated_at":{"format":"date-time","type":"string"},"years":{"description":"Term actually purchased — may be clamped up to the TLD minimum.","type":"integer"}},"title":"Operation","type":"object"},"Me":{"description":"Who is calling: an API key and its account, or a signed-in app (a person, in the account named by X-OrbitFour-Account, if any).","properties":{"account":{"nullable":true,"properties":{"id":{"format":"uuid","type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"status":{"description":"Currently active, suspended, blocked. A plain string, not an enum, because statuses are added over time.","example":"active","type":"string"}},"required":["id","name","slug","status"],"type":"object"},"api_key":{"description":"The calling API key; null for an app or OAuth sign-in, which acts as a person (see user and app_session).","nullable":true,"properties":{"id":{"format":"uuid","type":"string"},"last_used_at":{"description":"The key's previous request, before this one (this request is recorded but not shown); null on its first.","format":"date-time","nullable":true,"type":"string"},"name":{"type":"string"},"rate_limit_per_min":{"type":"integer"},"scopes":{"items":{"type":"string"},"type":"array"}},"required":["id","name","scopes","rate_limit_per_min","last_used_at"],"type":"object"},"app_session":{"description":"The app or OAuth sign-in behind the token (one per device or client), with the scopes it was granted; null for an API key.","nullable":true,"properties":{"app_version":{"nullable":true,"type":"string"},"device_name":{"nullable":true,"type":"string"},"expires_at":{"description":"When the sign-in ends however active it is (90 days).","format":"date-time","type":"string"},"id":{"format":"uuid","type":"string"},"platform":{"nullable":true,"type":"string"},"scopes":{"items":{"type":"string"},"type":"array"}},"required":["id","platform","device_name","app_version","scopes","expires_at"],"type":"object"},"environment":{"description":"Which OrbitFour this is. Anything but production answers from a test registry (OT&E, or the sandbox's fake one): availability, prices and registrations there are not real.","enum":["production","sandbox","staging","development"],"type":"string"},"spending":{"description":"What the credential in use may spend today (UTC). daily_limit is the limit the owner set, null when none is set (then REST is uncapped and MCP purchases are capped at $100 a day). remaining_today is null with no limit set. requires_approval: each purchase waits for a person (API keys only). A quote checks the cap of its own surface.","properties":{"daily_limit":{"$ref":"#/components/schemas/NullableMoney"},"remaining_today":{"$ref":"#/components/schemas/NullableMoney"},"requires_approval":{"type":"boolean"},"spent_today":{"$ref":"#/components/schemas/NullableMoney"}},"required":["daily_limit","spent_today","remaining_today","requires_approval"],"type":"object"},"user":{"description":"The person signed in through the app or OAuth; null for an API key, which belongs to the account rather than a person.","nullable":true,"properties":{"email":{"format":"email","type":"string"},"id":{"format":"uuid","type":"string"}},"required":["id","email"],"type":"object"}},"required":["environment","account","spending","api_key","user","app_session"],"title":"Me","type":"object"},"Badge":{"description":"The app icon's badge: events that would have been pushed to the signed-in person, across their accounts, since they last opened the notification feed. Every push carries the same count.","properties":{"seen_at":{"description":"When the feed was last opened; null before the first device registers.","format":"date-time","nullable":true,"type":"string"},"unread":{"minimum":0,"type":"integer"}},"required":["unread","seen_at"],"title":"Badge","type":"object"},"Transaction":{"description":"A billing transaction. Stripe identifiers are never exposed; use `id` for reconciliation and `invoice_id` to join to invoices.","properties":{"amount":{"$ref":"#/components/schemas/Money"},"created_at":{"format":"date-time","type":"string"},"description":{"nullable":true,"type":"string"},"domain_id":{"format":"uuid","nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"invoice_id":{"format":"uuid","nullable":true,"type":"string"},"payment_path":{"description":"How the transaction settles: saved card or prepaid balance.","enum":["card","balance"],"type":"string"},"refunded_amount":{"$ref":"#/components/schemas/NullableMoney"},"status":{"enum":["pending","processing","succeeded","failed","canceled","requires_action","refunded","partially_refunded"],"type":"string"},"type":{"enum":["registration","renewal","transfer","refund","credit","adjustment","deposit"],"type":"string"}},"title":"Transaction","type":"object"},"TldPrice":{"properties":{"categories":{"items":{"type":"string"},"type":"array"},"eligibility":{"description":"Who may register a name on this extension.","properties":{"policy":{"description":"The registry's eligibility policy, when it publishes one.","type":"string"},"restricted":{"description":"true when the registry limits who may register: a community or profession, or a connection to a place. Every requires_nexus TLD is restricted, and registrant_schema says what its registrant contact must carry. false: anyone may.","type":"boolean"},"summary":{"description":"Who qualifies, when restricted.","type":"string"}},"required":["restricted"],"type":"object"},"https_required":{"description":"true when browsers load websites on this extension over HTTPS only, because the whole extension is on the HSTS preload list (.app, .dev, .page and others): a site needs a valid TLS certificate before it loads, and http:// links are upgraded. Email and other non-web services are unaffected.","type":"boolean"},"icann_fee":{"description":"Per-year ICANN fee, added on top of each price; \"0.00\" on a ccTLD, which owes none. check_domain reports the same amount.","type":"string"},"max_years":{"type":"integer"},"min_years":{"type":"integer"},"name":{"nullable":true,"type":"string"},"period_years":{"description":"The term each price covers: always 1, so every price is per year. A purchase costs it times its years (at least min_years).","example":1,"type":"integer"},"premium_possible":{"description":"Whether the registry can price a name above these standard prices; when true, check_domain quotes the name.","type":"boolean"},"registration":{"description":"Per-year retail price in the catalog's currency, as a decimal string.","nullable":true,"type":"string"},"renewal":{"description":"Per-year retail price in the catalog's currency, as a decimal string.","nullable":true,"type":"string"},"requires_nexus":{"type":"boolean"},"restore":{"description":"Per-year retail price in the catalog's currency, as a decimal string.","nullable":true,"type":"string"},"tld":{"example":"com","type":"string"},"transfer":{"description":"Per-year retail price in the catalog's currency, as a decimal string.","nullable":true,"type":"string"},"transfer_years":{"description":"Years a transfer in buys and is charged for, added to the expiry date. A transfer request takes no years: it's always this.","type":"integer"},"transfer_years_fixed":{"description":"true when the registry accepts exactly transfer_years on a transfer and no other period (PIR's .org: 1); false when transfer_years is this extension's shortest term (min_years).","type":"boolean"},"url":{"format":"uri","type":"string"},"whois_privacy":{"properties":{"price":{"type":"string"},"supported":{"type":"boolean"}},"required":["supported"],"type":"object"}},"required":["tld","name","registration","renewal","transfer","restore","icann_fee","period_years","min_years","max_years","transfer_years","transfer_years_fixed","requires_nexus","premium_possible","https_required","whois_privacy","eligibility","categories","url"],"title":"TldPrice","type":"object"},"PricingConstraints":{"description":"Account-wide rules that apply to every TLD.","properties":{"balance_currency":{"type":"string"},"docs":{"format":"uri","type":"string"},"grace_period_days":{"type":"integer"},"min_deposit":{"type":"string"},"premium_max_retail":{"type":"string"},"redemption_period_days":{"type":"integer"},"transfer_lock_days":{"description":"Days after a registration or a completed transfer in during which ICANN's Transfer Policy forbids moving a domain to another registrar (60). One domain's countdown is transfer_lock.days_until_transferable on GET /domains/{id} (get_domain).","type":"integer"}},"required":["transfer_lock_days","grace_period_days","redemption_period_days","balance_currency","min_deposit","premium_max_retail","docs"],"title":"PricingConstraints","type":"object"},"DepositInput":{"additionalProperties":false,"properties":{"amount":{"description":"USD amount to deposit, e.g. \"250.00\". Minimum $5.00.","example":"250.00","type":"string"},"payment_method":{"description":"Card to charge: \"default\" (or omit) for the default card, a payment-method UUID, or a last-four like \"4242\". An ambiguous last-four returns 409 with candidate ids.","example":"default","nullable":true,"type":"string"}},"required":["amount"],"title":"DepositInput","type":"object"},"CardSetup":{"properties":{"client_secret":{"description":"Pass to Stripe.js `confirmCardSetup`/Elements or the Stripe iOS SDK to collect and confirm the card. Treat as a secret.","type":"string"},"publishable_key":{"description":"The Stripe publishable key to initialise Stripe.js or the SDK with.","nullable":true,"type":"string"},"setup_intent_id":{"example":"seti_1Q2w3E4r5T6y7U8i","type":"string"},"status":{"example":"requires_payment_method","type":"string"}},"required":["setup_intent_id","client_secret","status"],"title":"CardSetup","type":"object"},"Actor":{"description":"Who did it: an API key, the OrbitFour app or an OAuth client acting for a person, or a person on the website. null when OrbitFour did it itself (an auto-renewal, a refund, a sync) or when it happened before this was recorded.","nullable":true,"properties":{"id":{"description":"The API key's id (whoami's api_key.id), the app or OAuth sign-in's id (app_session.id), or the person's user id.","format":"uuid","type":"string"},"name":{"description":"The key's or the app's name; null for a person.","nullable":true,"type":"string"},"type":{"enum":["api_key","app","oauth_client","user"],"type":"string"}},"required":["type","id","name"],"title":"Actor","type":"object"},"AuthCode":{"properties":{"auth_code":{"description":"The transfer authorization code. Treat it as a password: anyone holding it can request the domain.","type":"string"}},"title":"AuthCode","type":"object"},"AutoTopUp":{"description":"When a draw takes the balance under low_balance_threshold, the default card is charged off-session for enough to bring it back to target, never more than what's left of monthly_limit this UTC month. A failed charge turns it off and emails the owners. Null: off.","nullable":true,"properties":{"monthly_limit":{"$ref":"#/components/schemas/Money"},"spent_this_month":{"$ref":"#/components/schemas/Money"},"target":{"$ref":"#/components/schemas/Money"}},"title":"AutoTopUp","type":"object"},"CardSetupInput":{"additionalProperties":false,"properties":{"make_default":{"description":"Make the card the default once registered. The account's first card is always the default.","type":"boolean"},"nickname":{"description":"A label for the card, e.g. \"Ops corporate card\".","maxLength":60,"nullable":true,"type":"string"}},"title":"CardSetupInput","type":"object"},"NotificationPreferences":{"additionalProperties":false,"description":"Push categories for the signed-in person, across every account. Each is on unless turned off. action_needed: Something needs you: a failed operation, a transfer waiting on you, a declined auto-renewal charge, a purchase to approve. activity: Registrations, renewals and transfers completing. billing: Balance deposits and low-balance alerts. expiry: Domains about to expire. watchlist: Watched domains becoming available.","properties":{"action_needed":{"description":"Something needs you: a failed operation, a transfer waiting on you, a declined auto-renewal charge, a purchase to approve","type":"boolean"},"activity":{"description":"Registrations, renewals and transfers completing","type":"boolean"},"billing":{"description":"Balance deposits and low-balance alerts","type":"boolean"},"expiry":{"description":"Domains about to expire","type":"boolean"},"watchlist":{"description":"Watched domains becoming available","type":"boolean"}},"title":"NotificationPreferences","type":"object"},"WebhookDelivery":{"properties":{"attempts":{"type":"integer"},"created_at":{"format":"date-time","type":"string"},"delivered_at":{"format":"date-time","nullable":true,"type":"string"},"duration_ms":{"nullable":true,"type":"integer"},"error":{"nullable":true,"type":"string"},"event_id":{"format":"uuid","type":"string"},"event_type":{"type":"string"},"id":{"format":"uuid","type":"string"},"response_excerpt":{"description":"The first 500 bytes of your endpoint's response.","nullable":true,"type":"string"},"response_status":{"nullable":true,"type":"integer"},"status":{"description":"pending is still being retried.","enum":["pending","succeeded","failed"],"type":"string"}},"required":["id","event_id","event_type","status","attempts","created_at"],"title":"WebhookDelivery","type":"object"},"WatchlistItem":{"properties":{"added_by":{"description":"The user who added it.","format":"uuid","nullable":true,"type":"string"},"availability_status":{"description":"As of last_checked_at; check_domain is the live answer.","enum":["available","taken","unknown"],"type":"string"},"domain_name":{"type":"string"},"id":{"format":"uuid","type":"string"},"inserted_at":{"format":"date-time","type":"string"},"intent":{"description":"save keeps the name for later; notify also checks it daily and emails when it becomes available.","enum":["save","notify"],"type":"string"},"last_checked_at":{"format":"date-time","nullable":true,"type":"string"},"notified_at":{"format":"date-time","nullable":true,"type":"string"},"tld":{"type":"string"}},"required":["id","domain_name","tld","intent","availability_status","inserted_at"],"title":"WatchlistItem","type":"object"},"ContactInput":{"description":"Request body for creating/updating a contact. On create, name/address/phone/email are required (enforced by the changeset).","properties":{"address1":{"type":"string"},"address2":{"type":"string"},"app_purpose":{"description":".us application purpose (P1–P5)","type":"string"},"city":{"type":"string"},"country_code":{"example":"US","type":"string"},"default_admin":{"type":"boolean"},"default_billing":{"type":"boolean"},"default_registrant":{"type":"boolean"},"default_technical":{"type":"boolean"},"email":{"format":"email","type":"string"},"fax":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"nexus_category":{"description":".us Nexus category (C11/C12/C21/C31/C32)","type":"string"},"nexus_country":{"description":".us foreign country for C31/C32","type":"string"},"organization":{"type":"string"},"phone":{"example":"+1.5551234567","type":"string"},"phone_country_code":{"example":"+1","type":"string"},"postal_info":{"enum":["int","loc"],"type":"string"},"state":{"type":"string"},"title":{"type":"string"},"zip":{"type":"string"}},"title":"ContactInput","type":"object"},"PaymentMethodRegisterInput":{"additionalProperties":false,"properties":{"setup_intent_id":{"description":"The id returned by POST /payment_methods/setup_intents, after the client confirmed it with Stripe.","pattern":"^seti_[A-Za-z0-9_]+$","type":"string"}},"required":["setup_intent_id"],"title":"PaymentMethodRegisterInput","type":"object"},"TeamPermissionsInput":{"additionalProperties":false,"description":"Replaces the member's switched-off permissions: any role permission not sent as false is switched back on.","properties":{"permissions":{"$ref":"#/components/schemas/TeamPermissions"}},"required":["permissions"],"title":"TeamPermissionsInput","type":"object"},"PurchaseQuote":{"description":"A dry run's answer: what the operation would charge and how it would pay. Nothing was reserved, charged or written. Send quote_token back on the same request to buy exactly this within 10 minutes.","properties":{"action":{"enum":["registration","renewal","transfer"],"type":"string"},"auto_renew":{"description":"Whether the domain renews itself at renewal_total each term: a registration's own auto_renew (default true), a renewal's current setting. Null for a transfer.","nullable":true,"type":"boolean"},"auto_renew_max_price":{"description":"The most auto-renew may charge a year; null means no cap (a new registration never has one).","nullable":true,"properties":{"amount":{"example":"50.00","type":"string"},"currency":{"example":"USD","type":"string"}},"required":["amount","currency"],"type":"object"},"balance_sufficient":{"type":"boolean"},"domain_name":{"type":"string"},"expires_at":{"format":"date-time","type":"string"},"icann_fee":{"$ref":"#/components/schemas/Money"},"is_premium":{"type":"boolean"},"limit_sufficient":{"description":"Whether the credential's daily spend limit (UTC day) leaves room for this total; false means the purchase would be refused.","type":"boolean"},"payment_path":{"enum":["balance","card"],"type":"string"},"privacy":{"description":"A registration's WHOIS privacy (default true, forced off where the TLD forbids it). Null for a renewal or transfer.","nullable":true,"type":"boolean"},"quote_token":{"type":"string"},"registrant":{"$ref":"#/components/schemas/PurchaseRegistrant"},"remaining_today":{"$ref":"#/components/schemas/NullableMoney"},"renewal_total":{"description":"What each renewal year after this term costs, per year with the ICANN fee included (total covers only this term). Null for a transfer, or when the registry's renewal price couldn't be confirmed.","nullable":true,"properties":{"amount":{"example":"14.20","type":"string"},"currency":{"example":"USD","type":"string"}},"required":["amount","currency"],"type":"object"},"summary":{"description":"What a person approves: the first term, then what it commits to and who will own it, e.g. \"Registration of example.com, 1 year, $12.20 total, paid from the prepaid balance. Auto-renew will be on: it renews at $14.20 a year (ICANN fee included), with no price cap, until turned off. WHOIS privacy on. Registrant: Jane Doe (Acme Inc), US.\"","type":"string"},"total":{"$ref":"#/components/schemas/Money"},"unit_price":{"$ref":"#/components/schemas/Money"},"years":{"type":"integer"},"years_raised":{"description":"true when the years asked for were below the TLD's minimum term and were raised to it; years is the term quoted.","type":"boolean"}},"required":["action","domain_name","years","total","quote_token","expires_at","summary"],"title":"PurchaseQuote","type":"object"},"DomainDetail":{"properties":{"auto_renew":{"type":"boolean"},"auto_renew_terms":{"description":"What auto-renewal does when it runs; max_price_per_year null is no limit. Change them with PATCH /domains/{id}/settings.","properties":{"days_before":{"description":"Days before expiry that auto-renewal runs.","type":"integer"},"max_price_per_year":{"$ref":"#/components/schemas/NullableMoney"},"years":{"description":"Years each auto-renewal buys.","type":"integer"}},"type":"object"},"contacts":{"items":{"properties":{"contact_id":{"format":"uuid","type":"string"},"role":{"enum":["registrant","admin","technical","billing"],"type":"string"}},"type":"object"},"type":"array"},"custom_dns":{"type":"boolean"},"dns_provider":{"nullable":true,"type":"string"},"dnssec":{"properties":{"ds_records":{"items":{"properties":{"algorithm":{"type":"string"},"digest":{"type":"string"},"digest_type":{"type":"string"},"key_tag":{"type":"integer"}},"type":"object"},"type":"array"},"enabled":{"type":"boolean"}},"type":"object"},"domain_name":{"example":"example.com","type":"string"},"expiration_date":{"format":"date","nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"nameservers":{"items":{"type":"string"},"type":"array"},"privacy":{"type":"boolean"},"registration_date":{"format":"date","nullable":true,"type":"string"},"status":{"example":"Active","type":"string"},"tags":{"items":{"type":"string"},"type":"array"},"transfer_lock":{"properties":{"days_until_transferable":{"description":"Days left on the 60-day hold after registration or a transfer in; 0 once it has passed.","type":"integer"},"protective_lock_until":{"description":"Only on a name that came to OrbitFour in an ICANN-approved bulk transfer from another registrar, never on one its owner transferred in: until this date it can't be unlocked and its transfer code can't be replaced (it can still be read), which guards it against being moved out. The owner can release it early from the domain's page on the website. null when no such lock holds.","format":"date","nullable":true,"type":"string"}},"type":"object"},"transfer_locked":{"type":"boolean"}},"title":"DomainDetail","type":"object"},"Domain":{"properties":{"auto_renew":{"type":"boolean"},"custom_dns":{"type":"boolean"},"dns_provider":{"nullable":true,"type":"string"},"domain_name":{"example":"example.com","type":"string"},"expiration_date":{"format":"date","nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"nameservers":{"items":{"type":"string"},"type":"array"},"privacy":{"type":"boolean"},"registration_date":{"format":"date","nullable":true,"type":"string"},"status":{"example":"Active","type":"string"},"tags":{"items":{"type":"string"},"type":"array"},"transfer_locked":{"type":"boolean"}},"title":"Domain","type":"object"},"TeamInviteInput":{"additionalProperties":false,"properties":{"email":{"format":"email","maxLength":160,"type":"string"},"permissions":{"$ref":"#/components/schemas/TeamPermissions"},"role":{"description":"Owners may invite any of these; admins may invite members and viewers. Ownership isn't transferable by invitation.","enum":["admin","member","viewer"],"type":"string"}},"required":["email","role"],"title":"TeamInviteInput","type":"object"},"NullableMoney":{"description":"Same shape as Money, or null when there is no amount.","nullable":true,"properties":{"amount":{"example":"12.99","type":"string"},"currency":{"example":"USD","type":"string"}},"required":["amount","currency"],"title":"NullableMoney","type":"object"},"Contact":{"properties":{"address1":{"nullable":true,"type":"string"},"address2":{"nullable":true,"type":"string"},"city":{"nullable":true,"type":"string"},"country_code":{"nullable":true,"type":"string"},"defaults":{"properties":{"admin":{"type":"boolean"},"billing":{"type":"boolean"},"registrant":{"type":"boolean"},"technical":{"type":"boolean"}},"type":"object"},"email":{"format":"email","type":"string"},"fax":{"nullable":true,"type":"string"},"first_name":{"type":"string"},"id":{"format":"uuid","type":"string"},"last_name":{"type":"string"},"organization":{"nullable":true,"type":"string"},"phone":{"nullable":true,"type":"string"},"phone_country_code":{"nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"},"title":{"nullable":true,"type":"string"},"zip":{"nullable":true,"type":"string"}},"title":"Contact","type":"object"},"TransferCheck":{"description":"Whether a name can be transferred to OrbitFour now, and the full first-term price. Prices are null when no price can be quoted.","properties":{"domain_name":{"type":"string"},"icann_fee":{"$ref":"#/components/schemas/NullableMoney"},"is_premium":{"nullable":true,"type":"boolean"},"reasons":{"items":{"enum":["invalid_name","unsupported_tld","already_here","not_registered","locked","pending_transfer","pending_delete","premium_over_cap","price_unconfirmed","unknown"],"type":"string"},"type":"array"},"total":{"$ref":"#/components/schemas/NullableMoney"},"transfer_price":{"$ref":"#/components/schemas/NullableMoney"},"transfer_years":{"description":"The registry's transfer term (PIR's .org is fixed at 1).","nullable":true,"type":"integer"},"transferable":{"description":"true or false from the registry; null when it couldn't be asked just now (never read as locked).","nullable":true,"type":"boolean"}},"required":["domain_name","transferable","reasons"],"title":"TransferCheck","type":"object"},"DnsRecordInput":{"description":"Request body for creating/updating a DNS record. On create, name/type/value are required (enforced by the changeset).","properties":{"enabled":{"description":"Defaults to true. false marks the record as switched off in the DNS editor, but it is still published and answered: delete the record to take it out of DNS.","type":"boolean"},"name":{"description":"Record name: @ for the domain itself, or a subdomain such as www. A CNAME must be the only record at its name, and an ALIAS can't share a name with an A or AAAA.","example":"www","type":"string"},"priority":{"description":"For MX/SRV records","type":"integer"},"ttl":{"description":"Time to live, in seconds (default 3600).","example":3600,"type":"integer"},"type":{"description":"A, AAAA, ALIAS, CNAME, MX, TXT, NS, SRV, CAA or WR. ALIAS points a name at a hostname and answers with its addresses, which is how @ points at a hostname (a CNAME can't be at @). WR is a web redirect: value is an http:// or https:// URL, and web requests for the name get a 301 redirect to it. WR needs OrbitFour's DNS: a domain whose DNS is on Cloudflare can't use it.","example":"A","type":"string"},"value":{"description":"An IPv4 address (A), IPv6 address (AAAA), hostname (ALIAS, CNAME, MX, NS), any text (TXT), \"priority weight port target\" (SRV), \"flags tag value\" (CAA) or a URL (WR).","example":"203.0.113.4","type":"string"}},"title":"DnsRecordInput","type":"object"},"Account":{"properties":{"id":{"format":"uuid","type":"string"},"name":{"type":"string"},"slug":{"nullable":true,"type":"string"},"status":{"example":"active","type":"string"},"team":{"items":{"properties":{"email":{"format":"email","type":"string"},"role":{"example":"owner","type":"string"},"user_id":{"format":"uuid","type":"string"}},"type":"object"},"type":"array"}},"title":"Account","type":"object"},"LedgerEntry":{"description":"One append-only prepaid-balance ledger entry. `amount` is signed: positive credits the balance, negative draws it down.","properties":{"actor":{"$ref":"#/components/schemas/Actor"},"amount":{"$ref":"#/components/schemas/Money"},"balance_after":{"$ref":"#/components/schemas/Money"},"created_at":{"format":"date-time","type":"string"},"description":{"nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"transaction_id":{"format":"uuid","nullable":true,"type":"string"},"type":{"enum":["deposit","debit","reversal","refund_out","adjustment"],"type":"string"}},"title":"LedgerEntry","type":"object"},"DeletionRequest":{"description":"A request to delete the signed-in person's account. Staff complete it by removing the sign-in and personal details; invoices, payments and domain registration records are kept.","properties":{"complete_by":{"description":"The date we promise to have completed it by.","format":"date","type":"string"},"id":{"format":"uuid","type":"string"},"requested_at":{"format":"date-time","type":"string"},"source":{"enum":["web","app"],"type":"string"},"status":{"enum":["pending","completed","canceled"],"type":"string"}},"required":["id","status","source","requested_at","complete_by"],"title":"DeletionRequest","type":"object"},"Balance":{"properties":{"auto_top_up":{"$ref":"#/components/schemas/AutoTopUp"},"balance":{"$ref":"#/components/schemas/Money"},"below_threshold":{"description":"The balance is under low_balance_threshold. Null threshold (no alert): always false.","type":"boolean"},"low_balance_threshold":{"$ref":"#/components/schemas/NullableMoney"}},"title":"Balance","type":"object"},"PurchaseApproval":{"description":"A purchase a key that requires approval asked for, parked until someone who can edit billing decides. pending lapses to expired at expires_at; approved runs the purchase (operation_id), and failed means it was approved but didn't go through (failure).","properties":{"action":{"enum":["registration","renewal"],"type":"string"},"api_key":{"properties":{"id":{"format":"uuid","type":"string"},"name":{"type":"string"}},"type":"object"},"approval_url":{"format":"uri","type":"string"},"auto_renew":{"description":"Whether the domain renews itself at renewal_total each term once bought (a registration's own setting, a renewal's current one).","nullable":true,"type":"boolean"},"auto_renew_max_price":{"description":"The most auto-renew may charge a year; null means no cap.","nullable":true,"properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"type":"object"},"channel":{"enum":["rest","mcp"],"type":"string"},"client":{"description":"The MCP client that asked, when it said.","nullable":true,"type":"string"},"created_at":{"format":"date-time","type":"string"},"decided_at":{"format":"date-time","nullable":true,"type":"string"},"domain_name":{"type":"string"},"expires_at":{"format":"date-time","type":"string"},"failure":{"description":"Why an approved purchase didn't go through, e.g. insufficient_balance.","nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"operation_id":{"description":"Set once approved: poll GET /operations/{id}.","format":"uuid","nullable":true,"type":"string"},"privacy":{"description":"A registration's WHOIS privacy; null for a renewal.","nullable":true,"type":"boolean"},"registrant":{"$ref":"#/components/schemas/PurchaseRegistrant"},"renewal_total":{"description":"What each renewal year after this term costs, per year with the ICANN fee included, as quoted.","nullable":true,"properties":{"amount":{"type":"string"},"currency":{"type":"string"}},"required":["amount","currency"],"type":"object"},"retry_after":{"description":"Seconds to wait before polling again while it's undecided or its approved purchase is starting; null once there's nothing to wait for.","nullable":true,"type":"integer"},"status":{"enum":["pending","approved","declined","expired","failed"],"type":"string"},"terms":{"description":"The same commitments in words, as the quote's summary and the approval email put them. Empty for approvals parked before they were kept.","type":"string"},"total":{"$ref":"#/components/schemas/Money"},"years":{"type":"integer"}},"required":["id","status","action","domain_name","years","total","expires_at"],"title":"PurchaseApproval","type":"object"},"TeamMember":{"properties":{"email":{"format":"email","type":"string"},"joined_at":{"format":"date-time","nullable":true,"type":"string"},"permissions":{"$ref":"#/components/schemas/TeamPermissions"},"role":{"enum":["owner","admin","member","viewer"],"type":"string"},"two_factor_enabled":{"type":"boolean"},"user_id":{"format":"uuid","type":"string"},"you":{"description":"This member is the signed-in person.","type":"boolean"}},"required":["user_id","email","role","permissions","two_factor_enabled","you"],"title":"TeamMember","type":"object"},"DomainRenewInput":{"additionalProperties":false,"properties":{"dry_run":{"description":"true: answer 200 with a PurchaseQuote (the total, how it would pay, a quote_token) and charge nothing.","nullable":true,"type":"boolean"},"max_price":{"description":"Optional ceiling on this operation's full charge, as a USD decimal string: every year and the ICANN fee included, the same figure the response reports as amount. A higher charge is refused with 422 max_price_exceeded, which reports the price, and nothing is charged.","example":"50.00","nullable":true,"type":"string"},"payment_method":{"description":"\"balance\" forces the prepaid balance (402 if insufficient, no fallback); omit for balance-first with default-card fallback; \"default\", a payment-method UUID, or a last-four selects a card. An ambiguous last-four returns 409 with candidate ids.","example":"balance","nullable":true,"type":"string"},"quote_token":{"description":"From a dry run of this same operation, at most 10 minutes old. The purchase must match it; a higher live price is refused with quote_changed (and a fresh quote); a token is spent once, and sending it again returns the first operation.","nullable":true,"type":"string"},"years":{"description":"Renewal term. Defaults to (and is clamped up to) the TLD minimum; the response reports the term purchased.","maximum":10,"minimum":1,"nullable":true,"type":"integer"}},"title":"DomainRenewInput","type":"object"},"PriceCatalog":{"description":"Every TLD's retail prices and registry constraints, plus the account-wide constraints. Flat string amounts in `currency`.","properties":{"constraints":{"$ref":"#/components/schemas/PricingConstraints"},"count":{"type":"integer"},"currency":{"example":"USD","type":"string"},"generated_at":{"format":"date","type":"string"},"registrar":{"properties":{"iana_id":{"type":"string"},"name":{"type":"string"},"url":{"format":"uri","type":"string"}},"required":["name","iana_id","url"],"type":"object"},"tlds":{"items":{"$ref":"#/components/schemas/TldPrice"},"type":"array"}},"required":["registrar","currency","count","generated_at","constraints","tlds"],"title":"PriceCatalog","type":"object"},"Event":{"description":"Something that happened to the account. The same object is the body of a webhook delivery. data is thin: ids, names and codes, never auth codes, contact details or card data. data.actor, where the type lists it, is who did it (an API key, app, OAuth client or person; see Actor), null when OrbitFour acted itself. Kept 30 days.","properties":{"account_id":{"format":"uuid","type":"string"},"api_version":{"description":"The payload version; it changes only with a breaking change to data.","type":"string"},"created_at":{"format":"date-time","type":"string"},"data":{"additionalProperties":true,"description":"Per type; see the event catalog in /llms-full.txt.","type":"object"},"id":{"description":"Stable across webhook retries: use it to drop duplicates.","format":"uuid","type":"string"},"type":{"enum":["domain.registered","domain.renewed","domain.transfer_completed","domain.operation_failed","domain.action_required","domain.transfer_out_requested","domain.transferred_out","domain.expiring","domain.renewal_payment_failed","domain.settings_changed","domain.nameservers_changed","dns.record_changed","watchlist.domain_available","balance.deposited","balance.low","purchase.approval_requested","webhook.test"],"type":"string"}},"required":["id","type","created_at","account_id","api_version","data"],"title":"Event","type":"object"},"DomainRegisterInput":{"additionalProperties":false,"properties":{"auto_renew":{"description":"Default true.","nullable":true,"type":"boolean"},"contact_id":{"description":"Registrant contact. Required (with complete nexus data) for nexus TLDs like .us.","format":"uuid","nullable":true,"type":"string"},"contacts":{"additionalProperties":false,"description":"Per-role contact assignment; values are contact UUIDs on this account.","nullable":true,"properties":{"admin":{"format":"uuid","type":"string"},"billing":{"format":"uuid","type":"string"},"registrant":{"format":"uuid","type":"string"},"technical":{"format":"uuid","type":"string"}},"type":"object"},"domain_name":{"example":"example.com","type":"string"},"dry_run":{"description":"true: answer 200 with a PurchaseQuote (the total, how it would pay, a quote_token) and charge nothing.","nullable":true,"type":"boolean"},"max_price":{"description":"Optional ceiling on this operation's full charge, as a USD decimal string: every year and the ICANN fee included, the same figure the response reports as amount. A higher charge is refused with 422 max_price_exceeded, which reports the price, and nothing is charged.","example":"50.00","nullable":true,"type":"string"},"payment_method":{"description":"\"balance\" forces the prepaid balance (402 if insufficient, no fallback); omit for balance-first with default-card fallback; \"default\", a payment-method UUID, or a last-four selects a card. An ambiguous last-four returns 409 with candidate ids.","example":"balance","nullable":true,"type":"string"},"privacy":{"description":"WHOIS privacy (default true). Forced off for TLDs that forbid it (.us).","nullable":true,"type":"boolean"},"quote_token":{"description":"From a dry run of this same operation, at most 10 minutes old. The purchase must match it; a higher live price is refused with quote_changed (and a fresh quote); a token is spent once, and sending it again returns the first operation.","nullable":true,"type":"string"},"years":{"description":"Registration term. Defaults to (and is clamped up to) the TLD minimum; the response reports the term purchased.","maximum":10,"minimum":1,"nullable":true,"type":"integer"}},"required":["domain_name"],"title":"DomainRegisterInput","type":"object"},"Invoice":{"description":"An invoice with line-item detail. `pdf_url` serves the rendered PDF (same account:read scope).","properties":{"created_at":{"format":"date-time","type":"string"},"due_date":{"format":"date","nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"invoice_number":{"example":"INV-1234567890-0123","type":"string"},"line_items":{"items":{"properties":{"description":{"type":"string"},"domain_id":{"format":"uuid","nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"quantity":{"type":"integer"},"total_price":{"$ref":"#/components/schemas/Money"},"unit_price":{"$ref":"#/components/schemas/Money"}},"type":"object"},"type":"array"},"paid_at":{"format":"date-time","nullable":true,"type":"string"},"pdf_url":{"example":"/api/v1/invoices/9b2f.../pdf","type":"string"},"status":{"enum":["draft","sent","paid","overdue","void","canceled"],"type":"string"},"subtotal":{"$ref":"#/components/schemas/Money"},"tax":{"$ref":"#/components/schemas/NullableMoney"},"total":{"$ref":"#/components/schemas/Money"},"transaction_id":{"format":"uuid","nullable":true,"type":"string"}},"title":"Invoice","type":"object"},"TeamInvitation":{"description":"A pending invitation. The invitee joins by following the emailed link; the token never leaves the email.","properties":{"email":{"format":"email","type":"string"},"expires_at":{"format":"date-time","type":"string"},"id":{"format":"uuid","type":"string"},"invited_by":{"format":"email","nullable":true,"type":"string"},"permissions":{"$ref":"#/components/schemas/TeamPermissions"},"role":{"enum":["admin","member","viewer"],"type":"string"},"sent_at":{"format":"date-time","type":"string"}},"required":["id","email","role","permissions","sent_at","expires_at"],"title":"TeamInvitation","type":"object"},"ContactCreateInput":{"description":"Request body for creating a contact.","properties":{"address1":{"type":"string"},"address2":{"type":"string"},"app_purpose":{"description":".us application purpose (P1–P5)","type":"string"},"city":{"type":"string"},"country_code":{"example":"US","type":"string"},"default_admin":{"type":"boolean"},"default_billing":{"type":"boolean"},"default_registrant":{"type":"boolean"},"default_technical":{"type":"boolean"},"email":{"format":"email","type":"string"},"fax":{"type":"string"},"first_name":{"type":"string"},"last_name":{"type":"string"},"nexus_category":{"description":".us Nexus category (C11/C12/C21/C31/C32)","type":"string"},"nexus_country":{"description":".us foreign country for C31/C32","type":"string"},"organization":{"type":"string"},"phone":{"example":"+1.5551234567","type":"string"},"phone_country_code":{"example":"+1","type":"string"},"postal_info":{"enum":["int","loc"],"type":"string"},"state":{"type":"string"},"title":{"type":"string"},"zip":{"type":"string"}},"required":["first_name","last_name","address1","city","zip","country_code","phone","email"],"title":"ContactCreateInput","type":"object"},"BalanceSettingsInput":{"additionalProperties":false,"properties":{"auto_top_up":{"additionalProperties":false,"description":"Null turns auto top-up off. On, it needs a low_balance_threshold (its trigger) below target.","nullable":true,"properties":{"monthly_limit":{"description":"Most auto top-up may charge per UTC month.","pattern":"^[0-9]+(\\.[0-9]{1,2})?$","type":"string"},"target":{"description":"USD balance to top up to, e.g. \"100.00\".","pattern":"^[0-9]+(\\.[0-9]{1,2})?$","type":"string"}},"required":["target","monthly_limit"],"type":"object"},"low_balance_threshold":{"description":"USD amount, e.g. \"20.00\"; null turns the alert off, and auto top-up with it.","nullable":true,"pattern":"^[0-9]+(\\.[0-9]{1,2})?$","type":"string"}},"title":"BalanceSettingsInput","type":"object"},"DeletionRequestInput":{"additionalProperties":false,"properties":{"reason":{"description":"Optional, for the staff who complete it.","maxLength":1000,"type":"string"}},"title":"DeletionRequestInput","type":"object"},"PaginationMeta":{"description":"Page-based pagination for every list endpoint (`?page=N&per_page=M`, per_page at most 100).","properties":{"page":{"example":1,"type":"integer"},"per_page":{"example":50,"type":"integer"},"total":{"example":120,"type":"integer"},"total_pages":{"example":3,"type":"integer"}},"required":["page","per_page","total","total_pages"],"title":"PaginationMeta","type":"object"},"BadgeClearInput":{"additionalProperties":false,"properties":{"through":{"description":"The created_at of the newest event the feed showed, so an event that arrived while it loaded stays unread. Defaults to now.","format":"date-time","type":"string"}},"title":"BadgeClearInput","type":"object"},"WebhookEndpointInput":{"additionalProperties":false,"properties":{"active":{"description":"false pauses deliveries; true re-enables a switched-off endpoint and clears its failure count.","type":"boolean"},"description":{"maxLength":200,"type":"string"},"events":{"description":"Event types to send; \"*\" is all of them, including ones added later. An endpoint is sent only the events the person who created it can see: balance, purchase-approval and renewal-payment events need billing access.","items":{"enum":["*","domain.registered","domain.renewed","domain.transfer_completed","domain.operation_failed","domain.action_required","domain.transfer_out_requested","domain.transferred_out","domain.expiring","domain.renewal_payment_failed","domain.settings_changed","domain.nameservers_changed","dns.record_changed","watchlist.domain_available","balance.deposited","balance.low","purchase.approval_requested","webhook.test"],"type":"string"},"minItems":1,"type":"array"},"url":{"description":"https only, resolving to a public address. Redirects aren't followed.","format":"uri","maxLength":2048,"type":"string"}},"title":"WebhookEndpointInput","type":"object"}},"securitySchemes":{"appOAuth":{"description":"Sign-in for OrbitFour's own apps: authorization code with PKCE (S256), public client, no client secret. Access tokens live 15 minutes; refresh tokens rotate on every use, and reusing one signs the device out. Metadata: /.well-known/oauth-authorization-server.","flows":{"authorizationCode":{"authorizationUrl":"https://www.orbitfour.com/oauth/authorize","refreshUrl":"https://www.orbitfour.com/oauth/token","scopes":{"account:read":"Granted in full to first-party apps; the role in each account limits it","billing:write":"Granted in full to first-party apps; the role in each account limits it","contacts:read":"Granted in full to first-party apps; the role in each account limits it","contacts:write":"Granted in full to first-party apps; the role in each account limits it","dns:read":"Granted in full to first-party apps; the role in each account limits it","dns:write":"Granted in full to first-party apps; the role in each account limits it","domains:read":"Granted in full to first-party apps; the role in each account limits it","domains:transfer":"Granted in full to first-party apps; the role in each account limits it","domains:write":"Granted in full to first-party apps; the role in each account limits it","webhooks:write":"Granted in full to first-party apps; the role in each account limits it"},"tokenUrl":"https://www.orbitfour.com/oauth/token"}},"type":"oauth2"},"bearerAuth":{"description":"OrbitFour API key: `Authorization: Bearer o4_live_...` in production, `o4_test_...` on the sandbox. A signed-in OrbitFour app sends its access token (`o4at_...`, see appOAuth) the same way, plus `X-OrbitFour-Account: <account id>` to pick the account to act in.","scheme":"bearer","type":"http"}}},"info":{"contact":{"email":"support@orbitfour.com","name":"OrbitFour","url":"https://www.orbitfour.com/developers"},"description":"Public REST API for OrbitFour domain management. Authenticate with an API key via `Authorization: Bearer o4_...`. Every authenticated response carries `x-ratelimit-limit`, `x-ratelimit-remaining`, and `x-ratelimit-reset` (seconds) headers; a 429 additionally carries `Retry-After`.\n\nThis spec is the endpoint reference. For end-to-end workflows, the full error-code catalog with retry semantics, and the registry constraints that would otherwise only surface as a 422, read `/llms-full.txt`.","termsOfService":"https://www.orbitfour.com/legal/terms","title":"OrbitFour API","version":"1.0.0","x-logo":{"altText":"OrbitFour","url":"https://www.orbitfour.com/images/logo.png"}},"openapi":"3.0.0","paths":{"/api/v1/approvals":{"get":{"callbacks":{},"operationId":"listPurchaseApprovals","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/PurchaseApproval"},"type":"array"}},"type":"object"}}},"description":"Pending approvals"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Purchases waiting for approval","tags":["Approvals"]}},"/api/v1/me/badge":{"get":{"callbacks":{},"description":"Read on launch to set the icon's badge; each push also carries it.","operationId":"getBadge","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Badge"}},"type":"object"}}},"description":"Badge"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"The app badge count","tags":["Notifications"]}},"/api/v1/webhook_endpoints/{id}/rotate_secret":{"post":{"callbacks":{},"description":"The old secret stops signing immediately; the new one is returned once. The response is no-store.","operationId":"rotateWebhookSecret","parameters":[{"description":"Webhook endpoint UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/WebhookEndpoint"}},"type":"object"}}},"description":"Webhook endpoint"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or role"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Replace the signing secret","tags":["Webhooks"]}},"/api/v1/payment_methods/{id}":{"delete":{"callbacks":{},"description":"Detaches the card at Stripe and deletes it. Removing the default card does NOT promote another one: until you set a new default, paid operations without balance cover fail with no_default_payment_method and auto-renew can't charge a card. Supports the Idempotency-Key header.","operationId":"deletePaymentMethod","parameters":[{"description":"Payment method UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The payment provider refused the removal"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Payment provider unavailable"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Remove a card","tags":["Billing"]},"patch":{"callbacks":{},"description":"Make a card the default, or change its nickname. Supports the Idempotency-Key header.","operationId":"updatePaymentMethod","parameters":[{"description":"Payment method UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentMethodUpdateInput"}}},"description":"Card fields","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/PaymentMethod"}},"type":"object"}}},"description":"Updated card"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Validation error"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Update a card","tags":["Billing"]}},"/api/v1/contacts":{"get":{"callbacks":{},"description":"Returns the account's contacts, paginated.","operationId":"listContacts","parameters":[{"description":"Page number (default 1)","in":"query","name":"page","required":false,"schema":{"type":"integer"}},{"description":"Items per page (default 50, max 100)","in":"query","name":"per_page","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Contact"},"type":"array"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"type":"object"}}},"description":"Contacts"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"List contacts","tags":["Contacts"]},"post":{"callbacks":{},"operationId":"createContact","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactCreateInput"}}},"description":"Contact","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Contact"}},"type":"object"}}},"description":"Created contact"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Validation error"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Create a contact","tags":["Contacts"]}},"/api/v1/transactions/{id}":{"get":{"callbacks":{},"operationId":"getTransaction","parameters":[{"description":"Transaction UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Transaction"}},"type":"object"}}},"description":"Transaction"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Get a transaction","tags":["Billing"]}},"/api/v1/balance/ledger":{"get":{"callbacks":{},"description":"The append-only statement of deposits, draws, reversals, refunds, and adjustments, newest first.","operationId":"listLedgerEntries","parameters":[{"description":"Page number (default 1)","in":"query","name":"page","required":false,"schema":{"type":"integer"}},{"description":"Items per page (default 50, max 100)","in":"query","name":"per_page","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/LedgerEntry"},"type":"array"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"type":"object"}}},"description":"Ledger entries"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"List balance ledger entries","tags":["Billing"]}},"/api/v1/events":{"get":{"callbacks":{},"description":"Kept 30 days. To poll, pass the newest id you have as `after` and you get only what came since. `type` filters to a comma-separated list of types.","operationId":"listEvents","parameters":[{"description":"Comma-separated event types","in":"query","name":"type","required":false,"schema":{"type":"string"}},{"description":"Only events newer than this event id","in":"query","name":"after","required":false,"schema":{"type":"string"}},{"description":"Page number (default 1)","in":"query","name":"page","required":false,"schema":{"type":"integer"}},{"description":"Items per page (default 50, max 100)","in":"query","name":"per_page","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Event"},"type":"array"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"type":"object"}}},"description":"Events"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"`after` names no event of this account"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"List the account's events, newest first","tags":["Events"]}},"/api/v1/approvals/{id}":{"get":{"callbacks":{},"description":"Poll after a purchase answered 403 approval_required. Once approved, operation_id is the purchase to poll.","operationId":"getPurchaseApproval","parameters":[{"description":"The approval id","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/PurchaseApproval"}},"type":"object"}}},"description":"Approval"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"One purchase approval","tags":["Approvals"]}},"/api/v1/me/deletion_request":{"delete":{"callbacks":{},"description":"The OrbitFour app only.","operationId":"cancelAccountDeletion","parameters":[],"responses":{"204":{"description":"Canceled"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No pending request"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Cancel the pending deletion request","tags":["Me"]},"get":{"callbacks":{},"description":"The OrbitFour app only. 404 when there is none.","operationId":"getDeletionRequest","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DeletionRequest"}},"type":"object"}}},"description":"The request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No pending request"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"The pending account deletion request","tags":["Me"]},"post":{"callbacks":{},"description":"The OrbitFour app only, signed in within the last 5 minutes (otherwise 403 reauthentication_required: sign in again, then retry). Staff complete it within 30 days; until then the sign-in works and the request can be canceled. Asking again returns the pending request (200).","operationId":"requestAccountDeletion","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletionRequestInput"}}},"description":"Reason","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DeletionRequest"}},"type":"object"}}},"description":"The request"},"201":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DeletionRequest"}},"type":"object"}}},"description":"The request"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Sign in again first"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Ask to have your account deleted","tags":["Me"]}},"/api/v1/domains/{id}/transfer_out/reject":{"post":{"callbacks":{},"description":"Needs domains:transfer. The domain stays in the account.","operationId":"rejectTransferOut","parameters":[{"description":"Domain UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DomainDetail"}},"type":"object"}}},"description":"The domain after the change"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or permission"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not possible in the domain's current state"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not valid for this domain"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The registry did not confirm the change"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Reject a pending transfer to another registrar","tags":["Domains"]}},"/api/v1/domains/{id}/lock":{"post":{"callbacks":{},"operationId":"lockDomain","parameters":[{"description":"Domain UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DomainDetail"}},"type":"object"}}},"description":"The domain after the change"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or permission"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not possible in the domain's current state"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not valid for this domain"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The registry did not confirm the change"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Lock the domain against transfer","tags":["Domains"]}},"/api/v1/webhook_endpoints":{"get":{"callbacks":{},"operationId":"listWebhookEndpoints","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/WebhookEndpoint"},"type":"array"}},"type":"object"}}},"description":"Endpoints"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"List webhook endpoints","tags":["Webhooks"]},"post":{"callbacks":{},"description":"Returns the signing secret once. Verify each delivery's X-OrbitFour-Signature (t=<unix>,v1=<hex HMAC-SHA256 of \"<t>.<body>\">) and drop repeats by event id. At most 10 endpoints per account.","operationId":"createWebhookEndpoint","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointInput"}}},"description":"Endpoint","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/WebhookEndpoint"}},"type":"object"}}},"description":"Webhook endpoint"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or role"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid URL or event types, or the endpoint limit is reached"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Add a webhook endpoint","tags":["Webhooks"]}},"/api/v1/domains/{id}/transfer_out/approve":{"post":{"callbacks":{},"description":"Needs domains:transfer. The domain leaves the account once the registry completes the transfer.","operationId":"approveTransferOut","parameters":[{"description":"Domain UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DomainDetail"}},"type":"object"}}},"description":"The domain after the change"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or permission"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not possible in the domain's current state"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not valid for this domain"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The registry did not confirm the change"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Approve a pending transfer to another registrar","tags":["Domains"]}},"/api/v1/contacts/{id}":{"delete":{"callbacks":{},"operationId":"deleteContact","parameters":[{"description":"Contact UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Archived"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Delete (archive) a contact","tags":["Contacts"]},"get":{"callbacks":{},"operationId":"getContact","parameters":[{"description":"Contact UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Contact"}},"type":"object"}}},"description":"Contact"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Get a contact","tags":["Contacts"]},"patch":{"callbacks":{},"operationId":"updateContact","parameters":[{"description":"Contact UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactInput"}}},"description":"Contact fields to update","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Contact"}},"type":"object"}}},"description":"Updated contact"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Validation error"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Update a contact","tags":["Contacts"]}},"/api/v1/invoices/{id}/pdf":{"get":{"callbacks":{},"operationId":"getInvoicePdf","parameters":[{"description":"Invoice UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/pdf":{"schema":{"format":"binary","type":"string"}}},"description":"Invoice PDF"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"PDF generation failed"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"PDF generation unavailable (renderer missing) or busy (all render slots in flight)"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Download an invoice PDF","tags":["Billing"]}},"/api/v1/approvals/{id}/approve":{"post":{"callbacks":{},"description":"The OrbitFour app only. Queues the purchase to run as the key asked; poll the approval for its operation_id or failure.","operationId":"approvePurchase","parameters":[{"description":"The approval id","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/PurchaseApproval"}},"type":"object"}}},"description":"Approval"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Already decided or expired"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Approve a purchase","tags":["Approvals"]}},"/api/v1/devices":{"post":{"callbacks":{},"description":"The OrbitFour app only. Call on every launch with the current APNs token; registering a token again moves it to this sign-in, so one phone never gets two people's pushes. Signing out (POST /oauth/revoke) stops its pushes.","operationId":"registerDevice","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceInput"}}},"description":"Device","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Device"}},"type":"object"}}},"description":"Registered"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Register this device for push","tags":["Notifications"]}},"/api/v1/domains/{domain_id}/dns":{"get":{"callbacks":{},"description":"Returns the domain's DNS records, paginated. A new domain on OrbitFour's DNS starts with parking records: an ALIAS at @ and a CNAME at www, both to parking.orbitfour.com. The NS records at @ name the domain's nameservers and can't be changed or deleted here.","operationId":"listDnsRecords","parameters":[{"description":"Domain UUID","in":"path","name":"domain_id","required":true,"schema":{"type":"string"}},{"description":"Page number (default 1)","in":"query","name":"page","required":false,"schema":{"type":"integer"}},{"description":"Items per page (default 50, max 100)","in":"query","name":"per_page","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/DnsRecord"},"type":"array"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"type":"object"}}},"description":"DNS records"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"List a domain's DNS records","tags":["DNS"]},"post":{"callbacks":{},"description":"A CNAME must be the only record at its name and an ALIAS can't share a name with an A or AAAA, so with the parking records in place an A at @ or www is refused (422 validation_failed; details.name names the record in the way by type, name, id and value). Update that record instead (its type can change) or delete it first.","operationId":"createDnsRecord","parameters":[{"description":"Domain UUID","in":"path","name":"domain_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsRecordCreateInput"}}},"description":"DNS record","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DnsRecord"}},"type":"object"}}},"description":"Created record"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Validation error"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Create a DNS record","tags":["DNS"]}},"/api/v1/invoices/{id}":{"get":{"callbacks":{},"operationId":"getInvoice","parameters":[{"description":"Invoice UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Invoice"}},"type":"object"}}},"description":"Invoice"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Get an invoice","tags":["Billing"]}},"/api/v1/operations/{id}/cancel":{"post":{"callbacks":{},"description":"The OrbitFour app only, for an operation in requires_payment or payment_failed (client_confirm) whose payment hasn't started authenticating or processing, by the person who started it or an owner or admin. The PaymentIntent is canceled and nothing is charged.","operationId":"cancelOperation","parameters":[{"description":"Operation UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Operation"}},"type":"object"}}},"description":"Canceled"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Started by someone else, and the caller isn't an owner or admin"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not waiting for an in-app payment, or its payment is already under way"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Cancel an in-app purchase that hasn't been paid","tags":["Operations"]}},"/api/v1/domains/{id}/auth_code":{"post":{"callbacks":{},"description":"Needs domains:transfer and an unlocked domain. The code comes from the registry, is never stored or cached here, and the read is audited. The response is no-store and Idempotency-Key is ignored.","operationId":"getDomainAuthCode","parameters":[{"description":"Domain UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/AuthCode"}},"type":"object"}}},"description":"The transfer authorization code"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or permission"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not possible in the domain's current state"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not valid for this domain"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The registry did not confirm the change"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Read the transfer authorization code","tags":["Domains"]}},"/api/v1/domains/check":{"get":{"callbacks":{},"description":"Public, unauthenticated, rate-limited exact-match availability and pricing lookup.","operationId":"checkDomains","parameters":[{"description":"Comma-separated domain names (max 10)","in":"query","name":"names","required":true,"schema":{"type":"string"}},{"description":"Registration years (default 1)","in":"query","name":"years","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"domains":{"items":{"oneOf":[{"$ref":"#/components/schemas/DomainQuote"},{"$ref":"#/components/schemas/DomainCheckError"}]},"type":"array"}},"required":["domains"],"type":"object"}}},"description":"Availability + pricing"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Bad request"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Per-IP rate limit exceeded"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"summary":"Check domain availability + price","tags":["Public"]}},"/api/v1/transactions":{"get":{"callbacks":{},"description":"The account's billing transactions, newest first. Stripe identifiers are never exposed.","operationId":"listTransactions","parameters":[{"description":"Page number (default 1)","in":"query","name":"page","required":false,"schema":{"type":"integer"}},{"description":"Items per page (default 50, max 100)","in":"query","name":"per_page","required":false,"schema":{"type":"integer"}},{"description":"Filter by transaction type","in":"query","name":"type","required":false,"schema":{"enum":["registration","renewal","transfer","refund","credit","adjustment","deposit"],"type":"string"}},{"description":"Filter by status","in":"query","name":"status","required":false,"schema":{"enum":["pending","processing","succeeded","failed","canceled","requires_action","refunded","partially_refunded"],"type":"string"}},{"description":"Created on or after (ISO 8601 date, inclusive)","in":"query","name":"from","required":false,"schema":{"format":"date","type":"string"}},{"description":"Created on or before (ISO 8601 date, inclusive)","in":"query","name":"to","required":false,"schema":{"format":"date","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Transaction"},"type":"array"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"type":"object"}}},"description":"Transactions"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"List transactions","tags":["Billing"]}},"/api/v1/pricing/{tld}":{"get":{"callbacks":{},"description":"The listPrices entry for one TLD, plus JSON Schemas for what registering it requires: `registration_schema` (the TLD-specific part of the POST /domains body) and `registrant_schema` (fields the registrant contact must carry, e.g. .us Nexus). Both are {} for an unrestricted TLD. 404 tld_not_found when OrbitFour doesn't sell the TLD.","operationId":"getTldRequirements","parameters":[{"description":"The extension, e.g. us (a leading dot is ignored)","in":"path","name":"tld","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"constraints":{"$ref":"#/components/schemas/PricingConstraints"},"data":{"$ref":"#/components/schemas/TldRequirements"}},"required":["data","constraints"],"type":"object"}}},"description":"TLD requirements"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"OrbitFour does not sell this TLD"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Per-IP rate limit exceeded"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"summary":"One TLD's prices, policy and registration requirements","tags":["Public"]}},"/api/v1/devices/{token}":{"delete":{"callbacks":{},"operationId":"unregisterDevice","parameters":[{"description":"The APNs device token","in":"path","name":"token","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not registered to you"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Stop push to this device","tags":["Notifications"]}},"/api/v1/team/invitations/{id}":{"delete":{"callbacks":{},"description":"The OrbitFour app only. The emailed link stops working.","operationId":"revokeTeamInvitation","parameters":[{"description":"Invitation UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Revoked"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not the OrbitFour app, or the role doesn't allow it"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not valid"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Revoke a pending invitation","tags":["Team"]}},"/api/v1/watchlist":{"get":{"callbacks":{},"operationId":"listWatchlist","parameters":[{"description":"Page number (default 1)","in":"query","name":"page","required":false,"schema":{"type":"integer"}},{"description":"Items per page (default 50, max 100)","in":"query","name":"per_page","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/WatchlistItem"},"type":"array"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"type":"object"}}},"description":"Watchlist"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"List the watchlist","tags":["Watchlist"]},"post":{"callbacks":{},"description":"201 for a new entry; 200 when the name was already there (with notify, a saved name starts being watched).","operationId":"addToWatchlist","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistInput"}}},"description":"Domain","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/WatchlistItem"}},"type":"object"}}},"description":"Already on the watchlist"},"201":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/WatchlistItem"}},"type":"object"}}},"description":"Added"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not a valid domain name"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Add a domain to the watchlist","tags":["Watchlist"]}},"/api/v1/team/members/{user_id}":{"delete":{"callbacks":{},"description":"The OrbitFour app only. Owners can't be removed, and nobody can remove themselves. API keys they created are revoked.","operationId":"removeTeamMember","parameters":[{"description":"The member's user UUID","in":"path","name":"user_id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not the OrbitFour app, or the role doesn't allow it"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not valid"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Remove a member from the account","tags":["Team"]},"patch":{"callbacks":{},"description":"The OrbitFour app only; owners. Owners' own permissions can't be limited.","operationId":"updateTeamMemberPermissions","parameters":[{"description":"The member's user UUID","in":"path","name":"user_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamPermissionsInput"}}},"description":"Permissions","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/TeamMember"}},"type":"object"}}},"description":"The member after the change"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not the OrbitFour app, or the role doesn't allow it"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not valid"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Switch a member's permissions on or off","tags":["Team"]}},"/api/v1/webhook_endpoints/{id}/test":{"post":{"callbacks":{},"description":"Delivered to this endpoint only, whatever it subscribes to. Check the result under its deliveries.","operationId":"testWebhookEndpoint","parameters":[{"description":"Webhook endpoint UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"202":{"content":{"application/json":{"schema":{"properties":{"data":{"properties":{"queued":{"type":"boolean"}},"type":"object"}},"type":"object"}}},"description":"Queued"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or role"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Send a webhook.test event to this endpoint","tags":["Webhooks"]}},"/api/v1/me":{"get":{"callbacks":{},"description":"Returns the caller: an API key and its account, or a signed-in app's user and device sign-in.","operationId":"getMe","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}},"description":"Identity"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Whoami","tags":["Account"]}},"/api/v1/domains/{id}/settings":{"patch":{"callbacks":{},"description":"Changes only the fields sent. A field already at the requested value is left alone. The auto-renew terms take the same choices as the domain page, and a change to them is audited with the old and new values.","operationId":"updateDomainSettings","parameters":[{"description":"Domain UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainSettingsInput"}}},"description":"Settings","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DomainDetail"}},"type":"object"}}},"description":"The domain after the change"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or permission"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not possible in the domain's current state"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not valid for this domain"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The registry did not confirm the change"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Change auto-renew, its terms, or privacy","tags":["Domains"]}},"/api/v1/me/badge/clear":{"post":{"callbacks":{},"description":"Call when the person opens the notification feed (GET /events); the badge counts from here, on every device.","operationId":"clearBadge","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadgeClearInput"}}},"description":"Through","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Badge"}},"type":"object"}}},"description":"Badge"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Mark the notification feed seen","tags":["Notifications"]}},"/api/v1/webhook_endpoints/{id}":{"delete":{"callbacks":{},"operationId":"deleteWebhookEndpoint","parameters":[{"description":"Webhook endpoint UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or role"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Remove a webhook endpoint","tags":["Webhooks"]},"get":{"callbacks":{},"operationId":"getWebhookEndpoint","parameters":[{"description":"Webhook endpoint UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/WebhookEndpoint"}},"type":"object"}}},"description":"Webhook endpoint"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or role"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Get a webhook endpoint","tags":["Webhooks"]},"patch":{"callbacks":{},"description":"Send active: true to turn a switched-off endpoint back on.","operationId":"updateWebhookEndpoint","parameters":[{"description":"Webhook endpoint UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointInput"}}},"description":"Changes","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/WebhookEndpoint"}},"type":"object"}}},"description":"Webhook endpoint"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or role"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Change a webhook endpoint","tags":["Webhooks"]}},"/api/v1/webhook_endpoints/{id}/deliveries":{"get":{"callbacks":{},"operationId":"listWebhookDeliveries","parameters":[{"description":"Webhook endpoint UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Page number (default 1)","in":"query","name":"page","required":false,"schema":{"type":"integer"}},{"description":"Items per page (default 50, max 100)","in":"query","name":"per_page","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/WebhookDelivery"},"type":"array"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"type":"object"}}},"description":"Deliveries"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or role"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"List an endpoint's recent deliveries","tags":["Webhooks"]}},"/api/v1/account":{"get":{"callbacks":{},"operationId":"getAccount","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Account"}},"type":"object"}}},"description":"Account"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Get the account and its team","tags":["Account"]}},"/api/v1/events/{id}":{"get":{"callbacks":{},"operationId":"getEvent","parameters":[{"description":"Event UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Event"}},"type":"object"}}},"description":"Event"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Get an event","tags":["Events"]}},"/api/v1/invoices":{"get":{"callbacks":{},"description":"The account's invoices with line-item detail, newest first.","operationId":"listInvoices","parameters":[{"description":"Page number (default 1)","in":"query","name":"page","required":false,"schema":{"type":"integer"}},{"description":"Items per page (default 50, max 100)","in":"query","name":"per_page","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Invoice"},"type":"array"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"type":"object"}}},"description":"Invoices"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"List invoices","tags":["Billing"]}},"/api/v1/operations/{id}":{"get":{"callbacks":{},"description":"Status of an async paid operation (registration, renewal, or transfer) created via the API. Derived live from the payment and fulfillment records.","operationId":"getOperation","parameters":[{"description":"Operation UUID (returned by the 202 response)","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Operation"}},"type":"object"}}},"description":"Operation"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Get a paid operation's status","tags":["Operations"]}},"/api/v1/team/invitations":{"get":{"callbacks":{},"description":"The OrbitFour app only; owners and admins.","operationId":"listTeamInvitations","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/TeamInvitation"},"type":"array"}},"type":"object"}}},"description":"Invitations"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not the OrbitFour app, or the role doesn't allow it"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not valid"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"List pending invitations","tags":["Team"]},"post":{"callbacks":{},"description":"The OrbitFour app only. Emails an invitation link. Inviting an address with a pending invitation sends a fresh one and the old link stops working. At most one invitation per address per minute.","operationId":"inviteTeamMember","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInviteInput"}}},"description":"Invitation","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/TeamInvitation"}},"type":"object"}}},"description":"Invitation sent"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not the OrbitFour app, or the role doesn't allow it"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Already a member"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not valid"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Sent too recently"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Invite someone to the account","tags":["Team"]}},"/api/v1/me/notification_preferences":{"get":{"callbacks":{},"operationId":"getNotificationPreferences","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/NotificationPreferences"}},"type":"object"}}},"description":"Preferences"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Your push categories","tags":["Notifications"]},"patch":{"callbacks":{},"description":"Changes only the categories sent.","operationId":"updateNotificationPreferences","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferences"}}},"description":"Categories","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/NotificationPreferences"}},"type":"object"}}},"description":"Preferences"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unknown category"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Turn push categories on or off","tags":["Notifications"]}},"/api/v1/transfers/check":{"get":{"callbacks":{},"description":"Public, unauthenticated, rate-limited. Asks each name's registry whether it can be transferred now (lock, pending transfer or delete) and quotes the full first-term transfer price. Never takes an auth code; the paid transfer asks the registry again with it before charging.","operationId":"checkTransfers","parameters":[{"description":"Comma-separated domain names (max 5)","in":"query","name":"domains","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/TransferCheck"},"type":"array"}},"required":["data"],"type":"object"}}},"description":"Transfer checks"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Bad request"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Per-IP rate limit exceeded"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"summary":"Check whether domains can be transferred in, and the price","tags":["Public"]}},"/api/v1/balance/deposits":{"post":{"callbacks":{},"description":"Charges a saved card off-session and credits the prepaid balance. Synchronous: a 201 means the balance is already credited. Supports the Idempotency-Key header. A key that requires approval for purchases can't deposit (403 key_requires_approval).","operationId":"createDeposit","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DepositInput"}}},"description":"Deposit","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Balance"}},"type":"object"}}},"description":"Deposit credited"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Card declined / authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope, or a key that requires approval"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Ambiguous last-four"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Validation error"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Deposit funds","tags":["Billing"]}},"/api/v1/domains/{id}/renew":{"post":{"callbacks":{},"description":"Charges the prepaid balance (default) or a saved card, then renews the domain asynchronously. Returns 202 with an operation to poll at GET /api/v1/operations/{id}. Supports the Idempotency-Key header.","operationId":"renewDomain","parameters":[{"description":"Domain UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Opaque client-generated key. A replay of a completed request returns the original 202 and the same operation (response carries `idempotent-replayed: true`); a concurrent duplicate gets 409. Strongly recommended — without it, a retried request creates and pays for a second operation.","example":"reg-2026-07-24-001","in":"header","name":"Idempotency-Key","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainRenewInput"}}},"description":"Renewal","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/PurchaseQuote"}},"type":"object"}}},"description":"Dry run (dry_run: true): the quote, nothing charged"},"202":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Operation"}},"type":"object"}}},"description":"Operation accepted — poll GET /api/v1/operations/{id}","headers":{"idempotent-replayed":{"description":"Present and \"true\" when this 202 is a cached replay of an earlier request with the same Idempotency-Key.","schema":{"enum":["true"],"type":"string"},"style":"simple"}}},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient balance, declined card, or authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope, suspended account, or identity verification required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Domain or payment method not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Ambiguous payment method, duplicate operation, or payment already in progress"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Validation or pre-flight error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate or payment-velocity limited"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unexpected failure"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Registry could not confirm availability or price"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Renew a domain (paid)","tags":["Domains"]}},"/api/v1/domains/{id}/nameservers":{"put":{"callbacks":{},"description":"Sends the new set to the registry first and saves it here only once the registry has it.","operationId":"setDomainNameservers","parameters":[{"description":"Domain UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NameserversInput"}}},"description":"Nameservers","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DomainDetail"}},"type":"object"}}},"description":"The domain after the change"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or permission"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not possible in the domain's current state"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not valid for this domain"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The registry did not confirm the change"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Replace the nameservers","tags":["Domains"]}},"/api/v1/domains/{domain_id}/dns/{id}":{"delete":{"callbacks":{},"description":"The NS records at @ can't be deleted (422 protected_record): they name the nameservers that answer for the domain. To move its DNS, change the nameservers with PUT /domains/{id}/nameservers.","operationId":"deleteDnsRecord","parameters":[{"description":"Domain UUID","in":"path","name":"domain_id","required":true,"schema":{"type":"string"}},{"description":"Record UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"An NS record at @ (protected_record)"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Delete a DNS record","tags":["DNS"]},"patch":{"callbacks":{},"description":"Omitted fields stay as they are. The type can change too, e.g. the parking CNAME at www to an A. Refused like a create when the result would clash with another record at its name. The NS records at @ can't be changed (422 protected_record).","operationId":"updateDnsRecord","parameters":[{"description":"Domain UUID","in":"path","name":"domain_id","required":true,"schema":{"type":"string"}},{"description":"Record UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsRecordInput"}}},"description":"DNS record fields to update","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DnsRecord"}},"type":"object"}}},"description":"Updated record"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Validation error, or an NS record at @ (protected_record)"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Update a DNS record","tags":["DNS"]}},"/api/v1/watchlist/{id}":{"delete":{"callbacks":{},"operationId":"removeFromWatchlist","parameters":[{"description":"Watchlist item UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Removed"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Remove a domain from the watchlist","tags":["Watchlist"]}},"/api/v1/payment_methods/setup_intents":{"post":{"callbacks":{},"description":"Creates a Stripe SetupIntent for the account. Confirm it client-side with Stripe.js/Elements or the Stripe iOS SDK using `client_secret` and `publishable_key`, then call POST /payment_methods with the `setup_intent_id`. No card details ever pass through this API. Supports the Idempotency-Key header.","operationId":"createCardSetup","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CardSetupInput"}}},"description":"Card setup","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/CardSetup"}},"type":"object"}}},"description":"SetupIntent created"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope / account suspended"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Card limit reached / no billing email"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Card-setup limit exceeded"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Payment provider unavailable"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Start adding a card","tags":["Billing"]}},"/api/v1/domains":{"get":{"callbacks":{},"description":"Returns the account's domains, paginated.","operationId":"listDomains","parameters":[{"description":"Page number (default 1)","in":"query","name":"page","required":false,"schema":{"type":"integer"}},{"description":"Items per page (default 50, max 100)","in":"query","name":"per_page","required":false,"schema":{"type":"integer"}},{"description":"Filter by status. \"Active\" also matches domains in the 30-day \"Expiring Soon\" window (still registered, approaching expiry).","in":"query","name":"status","required":false,"schema":{"enum":["Active","Expired","Expiring Soon","Pending","Pending Delete","Pending Restore","TransferFailed","Transferred","Transferring In","Transferring Out"],"type":"string"}},{"description":"Filter by domain name substring","in":"query","name":"search","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Domain"},"type":"array"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"type":"object"}}},"description":"Domains"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"List domains","tags":["Domains"]},"post":{"callbacks":{},"description":"Charges the prepaid balance (default) or a saved card, then registers the domain asynchronously. Returns 202 with an operation to poll at GET /api/v1/operations/{id}. Supports the Idempotency-Key header.","operationId":"registerDomain","parameters":[{"description":"Opaque client-generated key. A replay of a completed request returns the original 202 and the same operation (response carries `idempotent-replayed: true`); a concurrent duplicate gets 409. Strongly recommended — without it, a retried request creates and pays for a second operation.","example":"reg-2026-07-24-001","in":"header","name":"Idempotency-Key","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainRegisterInput"}}},"description":"Registration","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/PurchaseQuote"}},"type":"object"}}},"description":"Dry run (dry_run: true): the quote, nothing charged"},"202":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Operation"}},"type":"object"}}},"description":"Operation accepted — poll GET /api/v1/operations/{id}","headers":{"idempotent-replayed":{"description":"Present and \"true\" when this 202 is a cached replay of an earlier request with the same Idempotency-Key.","schema":{"enum":["true"],"type":"string"},"style":"simple"}}},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient balance, declined card, or authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope, suspended account, or identity verification required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Domain or payment method not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Ambiguous payment method, duplicate operation, or payment already in progress"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Validation or pre-flight error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate or payment-velocity limited"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unexpected failure"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Registry could not confirm availability or price"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Register a domain (paid)","tags":["Domains"]}},"/api/v1/domains/{id}/unlock":{"post":{"callbacks":{},"description":"Needs domains:transfer. Refused while a protective lock or a registry (server) lock holds the domain.","operationId":"unlockDomain","parameters":[{"description":"Domain UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DomainDetail"}},"type":"object"}}},"description":"The domain after the change"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or permission"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not possible in the domain's current state"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not valid for this domain"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The registry did not confirm the change"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Unlock the domain for transfer","tags":["Domains"]}},"/api/v1/balance":{"get":{"callbacks":{},"description":"The account's current prepaid balance (USD). Paid operations draw on this balance by default.","operationId":"getBalance","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Balance"}},"type":"object"}}},"description":"Balance"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Get the prepaid balance","tags":["Billing"]}},"/api/v1/domains/search":{"get":{"callbacks":{},"description":"Public, unauthenticated, rate-limited generative discovery: a free-text seed in; top picks (the name as typed and the SLD on .com/.net/.org, with their real status) and ranked available priced suggestions out. A phrase yields short combinations of its words. What didn't come back is accounted for: unchecked_names, left_out, and with tlds, a reason per extension. Search is advisory: check_domain is the live answer for one name, and a purchase re-checks.","operationId":"searchDomains","parameters":[{"description":"Free-text search seed","in":"query","name":"q","required":true,"schema":{"type":"string"}},{"description":"Comma-separated TLDs to restrict the top picks and suggestions to (e.g. com,app,io). The SLD on each becomes a top pick, and the response's tlds says why any of them found nothing.","in":"query","name":"tlds","required":false,"schema":{"type":"string"}},{"description":"Max suggestions","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"Registration years (default 1)","in":"query","name":"years","required":false,"schema":{"type":"integer"}},{"description":"Leave out suggestions whose first_term.total, the first term's price with the ICANN fee (what the purchase charges), is above this USD amount, e.g. 25.00","in":"query","name":"max_price","required":false,"schema":{"type":"string"}},{"description":"false leaves premium names out of the suggestions (default true)","in":"query","name":"include_premium","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"},"left_out":{"description":"How many checked candidates aren't suggestions, by reason, so a short list explains itself: over_limit (past limit), over_max_price, premium (include_premium is false), premium_over_cap (above the purchase cap), price_unconfirmed (the registry's price didn't arrive), unchecked (no answer) and unavailable (taken or reserved).","properties":{"over_limit":{"minimum":0,"type":"integer"},"over_max_price":{"minimum":0,"type":"integer"},"premium":{"minimum":0,"type":"integer"},"premium_over_cap":{"minimum":0,"type":"integer"},"price_unconfirmed":{"minimum":0,"type":"integer"},"unavailable":{"minimum":0,"type":"integer"},"unchecked":{"minimum":0,"type":"integer"}},"required":["over_limit","over_max_price","premium","premium_over_cap","price_unconfirmed","unchecked","unavailable"],"type":"object"},"query":{"type":"string"},"suggestions":{"description":"Available names, never one of the top picks.","items":{"$ref":"#/components/schemas/DomainQuote"},"type":"array"},"tlds":{"description":"With tlds, one entry per extension asked for, in that order; null without it.","items":{"properties":{"found":{"description":"Available names on it that pass max_price and include_premium, top picks included.","minimum":0,"type":"integer"},"reason":{"description":"Why found is 0, null otherwise: unsupported (not sold here), over_max_price (its standard first term is above max_price, or every available name on it was), not_searched (the search's bounded pool ran out first), or the left_out reason that kept its names out, the first that applies in left_out's order.","enum":["unsupported","not_searched","over_limit","over_max_price","premium","premium_over_cap","price_unconfirmed","unchecked","unavailable",null],"nullable":true,"type":"string"},"tld":{"type":"string"}},"required":["tld","found","reason"],"type":"object"},"nullable":true,"type":"array"},"top_picks":{"description":"The name as typed (when its TLD isn't .com/.net/.org) and the SLD on .com, .net and .org, or with tlds on each extension listed (up to 12), taken or unknown included.","items":{"oneOf":[{"$ref":"#/components/schemas/DomainQuote"},{"$ref":"#/components/schemas/DomainCheckError"}]},"type":"array"},"unchecked":{"description":"How many names unchecked_names lists. A count, never an estimate.","type":"integer"},"unchecked_names":{"description":"Names whose check came back unknown (top picks included): not taken, just unanswered. Check them again to know.","items":{"type":"string"},"type":"array"}},"required":["query","top_picks","count","suggestions","unchecked","unchecked_names","left_out","tlds"],"type":"object"}}},"description":"Top picks and suggestions"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Bad request"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Per-IP rate limit exceeded"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"summary":"Search / generate available domains","tags":["Public"]}},"/api/v1/domains/{id}":{"get":{"callbacks":{},"operationId":"getDomain","parameters":[{"description":"Domain UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/DomainDetail"}},"type":"object"}}},"description":"Domain"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Get a domain","tags":["Domains"]}},"/api/v1/balance/settings":{"patch":{"callbacks":{},"description":"low_balance_threshold is a USD amount between 1.00 and 100000.00, or null to turn the alert off. The first draw that takes the balance under it emits balance.low (webhooks, app push) and emails the owners, once per crossing. auto_top_up {target, monthly_limit} makes that crossing charge the default card off-session back up to target instead of emailing; null turns it off. Send either field or both; a field left out is unchanged. A key that requires approval for purchases can't turn auto top-up on or change it (403 key_requires_approval); it can turn it off.","operationId":"updateBalanceSettings","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BalanceSettingsInput"}}},"description":"Settings","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Balance"}},"type":"object"}}},"description":"Balance"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope, or a key that requires approval turning on auto top-up"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Out of range"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Set the low-balance alert and auto top-up","tags":["Billing"]}},"/api/v1/pricing":{"get":{"callbacks":{},"description":"Public, cacheable price catalog for all enabled TLDs. Built for price aggregators, and the policy-discovery surface for API clients: each TLD carries its registry constraints (min_years, max_years, transfer_years, nexus + eligibility, WHOIS-privacy support) and a top-level `constraints` object carries the account-wide ones (60-day transfer lock, grace/redemption windows, USD-only balance, minimum deposit, premium review cap). Read this before building a request rather than discovering the rules from a 422.","operationId":"listPrices","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceCatalog"}}},"description":"Price catalog"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Per-IP rate limit exceeded"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"summary":"Full retail price catalog + policy discovery (JSON)","tags":["Public"]}},"/api/v1/pricing.csv":{"get":{"callbacks":{},"operationId":"getPricesCsv","parameters":[],"responses":{"200":{"content":{"text/csv":{"schema":{"type":"string"}}},"description":"Price catalog CSV"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Per-IP rate limit exceeded"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"summary":"Full retail price catalog (CSV)","tags":["Public"]}},"/api/v1/team/members":{"get":{"callbacks":{},"description":"The OrbitFour app only. Each member's role and the permissions they hold now.","operationId":"listTeamMembers","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/TeamMember"},"type":"array"}},"type":"object"}}},"description":"Members"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not the OrbitFour app, or the role doesn't allow it"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not valid"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"List the account's members","tags":["Team"]}},"/api/v1/app/version-check":{"get":{"callbacks":{},"description":"Our apps call this at launch. `update_required` is true when `build` is below the platform's minimum, which we raise when an older build can no longer work against the API. An unknown platform or a missing build never requires an update.","operationId":"checkAppVersion","parameters":[{"description":"ios","example":"ios","in":"query","name":"platform","required":true,"schema":{"type":"string"}},{"description":"The app's build number (CFBundleVersion), an integer","example":212,"in":"query","name":"build","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"properties":{"message":{"nullable":true,"type":"string"},"minimum_build":{"type":"integer"},"update_required":{"type":"boolean"}},"required":["update_required","minimum_build","message"],"type":"object"}},"required":["data"],"type":"object"}}},"description":"Version check"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Per-IP rate limit exceeded"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"summary":"Whether an app build must update before it can be used","tags":["Public"]}},"/api/v1/transfers":{"post":{"callbacks":{},"description":"Charges the prepaid balance (default) or a saved card, then requests the inbound transfer at the registry. The transfer term is fixed by registry policy per TLD. Returns 202 with an operation to poll at GET /api/v1/operations/{id}; registry approval itself can take up to 5 days. Supports the Idempotency-Key header.","operationId":"createTransfer","parameters":[{"description":"Opaque client-generated key. A replay of a completed request returns the original 202 and the same operation (response carries `idempotent-replayed: true`); a concurrent duplicate gets 409. Strongly recommended — without it, a retried request creates and pays for a second operation.","example":"reg-2026-07-24-001","in":"header","name":"Idempotency-Key","required":false,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferInput"}}},"description":"Transfer","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/PurchaseQuote"}},"type":"object"}}},"description":"Dry run (dry_run: true): the quote, nothing charged"},"202":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/Operation"}},"type":"object"}}},"description":"Operation accepted — poll GET /api/v1/operations/{id}","headers":{"idempotent-replayed":{"description":"Present and \"true\" when this 202 is a cached replay of an earlier request with the same Idempotency-Key.","schema":{"enum":["true"],"type":"string"},"style":"simple"}}},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient balance, declined card, or authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope, suspended account, or identity verification required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Domain or payment method not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Ambiguous payment method, duplicate operation, or payment already in progress"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Validation or pre-flight error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Rate or payment-velocity limited"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unexpected failure"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Registry could not confirm availability or price"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Transfer a domain in (paid)","tags":["Transfers"]}},"/api/v1/payment_methods":{"get":{"callbacks":{},"operationId":"listPaymentMethods","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"items":{"$ref":"#/components/schemas/PaymentMethod"},"type":"array"}},"type":"object"}}},"description":"Payment methods"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Insufficient scope"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"List payment methods","tags":["Billing"]},"post":{"callbacks":{},"description":"Records the card from a SetupIntent that the client confirmed with Stripe. Idempotent: registering the same SetupIntent again returns the existing card with 200. Supports the Idempotency-Key header.","operationId":"registerPaymentMethod","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentMethodRegisterInput"}}},"description":"SetupIntent","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/PaymentMethod"}},"type":"object"}}},"description":"Card already registered"},"201":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/PaymentMethod"}},"type":"object"}}},"description":"Card registered"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No such SetupIntent on this account"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"SetupIntent not confirmed yet"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"SetupIntent canceled / card removed / card limit reached"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Payment provider unavailable"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Register a confirmed card","tags":["Billing"]}},"/api/v1/me/accounts":{"get":{"callbacks":{},"description":"For a signed-in app, every account the person belongs to, with their role; send one id as X-OrbitFour-Account. For an API key, its own account.","operationId":"listMyAccounts","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeAccountList"}}},"description":"Accounts"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"List the accounts you can act in","tags":["Account"]}},"/api/v1/approvals/{id}/decline":{"post":{"callbacks":{},"description":"The OrbitFour app only. Nothing is charged.","operationId":"declinePurchase","parameters":[{"description":"The approval id","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/PurchaseApproval"}},"type":"object"}}},"description":"Approval"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Already decided or expired"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Decline a purchase","tags":["Approvals"]}},"/api/v1/domains/{id}/auth_code/rotate":{"post":{"callbacks":{},"description":"Needs domains:transfer, an unlocked domain past its 60-day hold and no pending transfer. The old code stops working. The new one is returned once and not kept here; the response is no-store.","operationId":"rotateDomainAuthCode","parameters":[{"description":"Domain UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/AuthCode"}},"type":"object"}}},"description":"The transfer authorization code"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or permission"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not possible in the domain's current state"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not valid for this domain"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The registry did not confirm the change"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Replace the transfer authorization code","tags":["Domains"]}},"/api/v1/webhook_endpoints/{id}/deliveries/{delivery_id}/redeliver":{"post":{"callbacks":{},"operationId":"redeliverWebhook","parameters":[{"description":"Webhook endpoint UUID","in":"path","name":"id","required":true,"schema":{"type":"string"}},{"description":"Delivery UUID","in":"path","name":"delivery_id","required":true,"schema":{"type":"string"}}],"responses":{"202":{"content":{"application/json":{"schema":{"properties":{"data":{"$ref":"#/components/schemas/WebhookDelivery"}},"type":"object"}}},"description":"Queued"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Missing scope or role"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"default":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"}},"security":[{"bearerAuth":[]}],"summary":"Send a delivery's event again","tags":["Webhooks"]}}},"security":[],"servers":[{"description":"Production","url":"https://www.orbitfour.com","variables":{}},{"description":"Sandbox: fake registry, Stripe test mode, o4_test_ keys","url":"https://sandbox.orbitfour.com","variables":{}}],"tags":[]}