{"openapi":"3.1.0","info":{"title":"Registrar Domains API","version":"0.6.0","description":"REST mirror of the MCP tools at /mcp (bearer API key). Live prices in USD before VAT, first year and renewal. Registration and renewal need a bearer API key and answer an order with a payment link for the human. Create keys in the dashboard after signing in at /signin. The read routes also accept the dashboard session cookie; every write takes a key. New DNS records usually reach our nameservers within minutes; networks that saw an old answer keep it until its TTL runs out, and a TTL change can take the old TTL plus an hour. An unlock, a transfer code, a nameserver change and turning auto-renew on wait for the owner's email confirmation and answer 202 (ConfirmationSent)."},"servers":[{"url":"https://registrar-domains.com"}],"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer"},"session":{"type":"apiKey","in":"cookie","name":"__Host-apex_session"}},"schemas":{"ConfirmationSent":{"type":"object","required":["status","domain","action","expiresAt","message"],"properties":{"status":{"type":"string","enum":["confirmation_sent"]},"domain":{"type":"string"},"action":{"type":"string","enum":["unlock","authcode","nameservers","autorenew_on","dnssec_off"]},"expiresAt":{"type":"string","format":"date-time","description":"When the emailed link stops working, 30 minutes after it was sent"},"message":{"type":"string"},"alreadySent":{"type":"boolean","enum":[true],"description":"The same request is open already: no new email was sent"},"warnings":{"type":"array","items":{"type":"string"},"description":"Nameservers only: the hosts public DNS does not find, one sentence each. Absent when there are none. They never block the request."},"recordWarnings":{"type":"array","items":{"type":"string"},"description":"A move to Cloudflare only: the records that stop working unless they are in Cloudflare, one sentence per group. Information only: the owner sees them again on the confirmation page."}}}}},"paths":{"/api/check":{"get":{"operationId":"check_domain","parameters":[{"name":"domain","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Availability","content":{"application/json":{"schema":{"type":"object","required":["domain","availability","source","checkedAt"],"properties":{"domain":{"type":"string"},"availability":{"type":"string","enum":["available","taken","unknown"]},"source":{"type":"string","enum":["rdap","registrar","apex","none"],"description":"registrar: the TLD has no public RDAP server, our registrar answered. apex: we already sold this name"},"checkedAt":{"type":"string","format":"date-time"},"reason":{"type":"string"}}}}}},"400":{"description":"Bad domain, or a name too short for the TLD's naming rule"},"429":{"description":"Rate limited"}}}},"/api/suggest":{"get":{"operationId":"suggest_domains","parameters":[{"name":"idea","in":"query","required":true,"schema":{"type":"string"},"description":"A word, a phrase, or a full domain (its TLD is tried first)"},{"name":"tlds","in":"query","required":false,"schema":{"type":"string"},"description":"Comma separated"}],"responses":{"200":{"description":"Ranked suggestions","content":{"application/json":{"schema":{"type":"object","properties":{"suggestions":{"type":"array","items":{"allOf":[{"type":"object","required":["domain","availability","source","checkedAt"],"properties":{"domain":{"type":"string"},"availability":{"type":"string","enum":["available","taken","unknown"]},"source":{"type":"string","enum":["rdap","registrar","apex","none"],"description":"registrar: the TLD has no public RDAP server, our registrar answered. apex: we already sold this name"},"checkedAt":{"type":"string","format":"date-time"},"reason":{"type":"string"}}},{"type":"object","properties":{"price":{"type":"object","required":["tld","price","renewPrice","cost","renew","renewCost","minYears","currency"],"properties":{"tld":{"type":"string"},"price":{"type":"number","description":"Our price for the first year, in currency before VAT"},"renewPrice":{"type":"number","description":"Our price for each renewal year, in currency before VAT"},"cost":{"type":"number","description":"Registrar purchase price per year, in currency"},"renew":{"type":"number","deprecated":true,"description":"Registrar renewal price per year, in currency. The old name of renewCost; use renewCost."},"renewCost":{"type":"number","description":"Registrar renewal price per year, in currency"},"minYears":{"type":"integer"},"currency":{"type":"string","enum":["USD","EUR"]}}}}}]}}}}}}},"400":{"description":"An idea that cannot become a domain name"},"429":{"description":"Rate limited"}}}},"/api/price":{"get":{"operationId":"get_price","parameters":[{"name":"tld","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"One price or the launch list","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["tld","price","renewPrice","cost","renew","renewCost","minYears","currency"],"properties":{"tld":{"type":"string"},"price":{"type":"number","description":"Our price for the first year, in currency before VAT"},"renewPrice":{"type":"number","description":"Our price for each renewal year, in currency before VAT"},"cost":{"type":"number","description":"Registrar purchase price per year, in currency"},"renew":{"type":"number","deprecated":true,"description":"Registrar renewal price per year, in currency. The old name of renewCost; use renewCost."},"renewCost":{"type":"number","description":"Registrar renewal price per year, in currency"},"minYears":{"type":"integer"},"currency":{"type":"string","enum":["USD","EUR"]}}},{"type":"object","properties":{"pricing":{"type":"array","items":{"type":"object","required":["tld","price","renewPrice","cost","renew","renewCost","minYears","currency"],"properties":{"tld":{"type":"string"},"price":{"type":"number","description":"Our price for the first year, in currency before VAT"},"renewPrice":{"type":"number","description":"Our price for each renewal year, in currency before VAT"},"cost":{"type":"number","description":"Registrar purchase price per year, in currency"},"renew":{"type":"number","deprecated":true,"description":"Registrar renewal price per year, in currency. The old name of renewCost; use renewCost."},"renewCost":{"type":"number","description":"Registrar renewal price per year, in currency"},"minYears":{"type":"integer"},"currency":{"type":"string","enum":["USD","EUR"]}}}},"note":{"type":"string"}}}]}}}},"400":{"description":"A malformed TLD"},"404":{"description":"TLD not sold by our registrar"},"429":{"description":"Rate limited"},"503":{"description":"Catalogue unavailable","content":{"application/json":{"schema":{"type":"object","required":["error","source","code","category"],"properties":{"error":{"type":"string"},"source":{"type":"string"},"code":{"type":"integer"},"category":{"type":"string","enum":["auth","rate_limit","not_found","invalid","duplicate","insufficient_balance","upstream"]}}}}}}}}},"/api/register":{"post":{"operationId":"register_domain","security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["domain","registrant"],"properties":{"domain":{"type":"string"},"years":{"type":"integer","minimum":1,"maximum":10,"default":1},"registrant":{"type":"object","required":["firstname","lastname","address","postal","city","country","phone","email"],"properties":{"firstname":{"type":"string"},"lastname":{"type":"string"},"company":{"type":"string"},"address":{"type":"string"},"postal":{"type":"string","maxLength":16,"description":"Its shape is checked for the countries that use one, for example 75001 in FR"},"city":{"type":"string"},"country":{"type":"string","pattern":"^[A-Za-z]{2}$","description":"ISO 3166-1 alpha-2 code of a country or territory, any case, for example FR (the United Kingdom is GB). Only codes ISO assigns are taken: not UK, EL, EU or XK. A TLD with a residence rule (.fr, .eu and others) needs an eligible country, see /terms#eligibility"},"phone":{"type":"string","maxLength":40,"description":"+<calling code>.<number>, for example +33.612345678. +33612345678, +33 6 12 34 56 78, 0033… or a national number of the registrant's country are converted to that format, and its length is checked per country."},"state":{"type":"string"},"email":{"type":"string","format":"email"}}},"addons":{"type":"object","description":"Options for a domain, each true or absent. Only the options this deployment offers are kept; privacy only where the registry takes it.","properties":{"privacy":{"type":"boolean"},"premiumDns":{"type":"boolean"},"spamExperts":{"type":"boolean"},"easyDmarc":{"type":"boolean"}}}}}}}},"responses":{"201":{"description":"Order created; pay at checkoutUrl","content":{"application/json":{"schema":{"type":"object","required":["orderId","kind","status","domain","years","lines","total","currency","statusUrl","policy"],"properties":{"orderId":{"type":"string"},"kind":{"type":"string","enum":["register","renew"],"description":"register: new domains; renew: years added to a domain of the account"},"status":{"type":"string","enum":["awaiting_payment","expired","paid","registering","registered","partly_failed","failed","refunded"],"description":"For a renewal, registered means renewed. The state is one of: awaiting_payment, expired, paid, registering, registered, partly_failed, failed, refunded. The final states: registered, partly_failed, failed, refunded, expired. partly_failed: some names were registered and the others were not; each line's status, and whether its refund is done or pending, is in lines[]."},"domain":{"type":"string","description":"The first line's domain; lines has them all"},"years":{"type":"integer","description":"The first line's years"},"lines":{"type":"array","items":{"type":"object","properties":{"lineId":{"type":"string"},"domain":{"type":"string"},"tld":{"type":"string"},"years":{"type":"integer"},"status":{"type":"string","enum":["pending","registering","registered","failed","refunded"]},"price":{"type":"number"},"renewPrice":{"type":["number","null"]},"addons":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"}}}},"addonsTotal":{"type":"number"},"total":{"type":"number","description":"The line, in the order's currency before VAT"},"registeredAt":{"type":["string","null"]},"heldUntil":{"type":["string","null"],"format":"date-time","description":"Set while the line waits for a registrar top-up. After this time, no new attempt is made: the line fails and a refund is started. The line status stays pending or registering meanwhile."},"failureReason":{"type":["string","null"]},"refunded":{"type":["number","null"],"description":"What came back for this line, VAT included"},"creditNote":{"type":["object","null"],"description":"The credit note that refunded this line","properties":{"number":{"type":["string","null"]},"url":{"type":"string","description":"Opens the credit note: GET /api/orders/{id}/credit-notes/{lineId}, with the order's view token"}}}}}},"total":{"type":"number","description":"In currency before VAT: the sum of the lines. A line: the first-year price, plus the larger of the first-year and renewal price for each extra year, plus its options per year. A renewal: the renewal price times the years, plus the options."},"currency":{"type":"string","enum":["USD","EUR"]},"checkoutUrl":{"type":["string","null"],"description":"Give this link to the human to pay. Present while the quote can be paid; null once it lapsed or closed. Nothing is charged until they pay."},"statusUrl":{"type":"string"},"expiresAt":{"type":"string","format":"date-time","description":"When the quote and its payment link expire"},"createdAt":{"type":"string","format":"date-time"},"registeredAt":{"type":["string","null"],"description":"When the last domain of the order was registered (or renewed); null when no domain was registered"},"failureReason":{"type":["string","null"]},"policy":{"type":"object"},"charged":{"type":["object","null"],"description":"What the buyer paid, VAT included. Null before payment, and for orders paid before amounts were recorded.","properties":{"total":{"type":"number"},"vat":{"type":"number"},"currency":{"type":"string","enum":["USD","EUR"]},"vatNote":{"type":["string","null"],"description":"Set on a reverse-charge sale"}}},"refunds":{"type":["object","null"],"description":"What went back to the card, VAT included: refunds made by us or by hand in Stripe, counted once each. A refund that failed does not count. Null when nothing was refunded. A refund never changes the order's status.","properties":{"total":{"type":"number","description":"Refunded and done"},"full":{"type":"boolean","description":"true when total reaches what was charged"},"pending":{"type":"number","description":"On its way to the card; 0 when none"}}},"invoice":{"type":["object","null"],"description":"Once the payment provider issued it. url opens it for the account (key or session); it carries the order's view token.","properties":{"number":{"type":["string","null"]},"url":{"type":"string"},"test":{"type":"boolean","description":"A test payment's invoice, not a tax document"}}}}}}}},"400":{"description":"Bad domain, registrant, or period; or a registrant country that the TLD's residence rule refuses (see /terms#eligibility; field: registrant.country), or a name too short for the TLD's naming rule (see /terms#eligibility)"},"401":{"description":"Missing or revoked API key"}}}},"/api/checkout":{"post":{"operationId":"web_checkout","description":"The website's checkout page: the signed-in person's basket, one registrant, one payment, behind a Cloudflare Turnstile check and 5 orders per hour per IP. Agents use checkout_basket or register_domain.","security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["registrant","turnstile","waiver"],"properties":{"lines":{"type":"array","items":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string"},"years":{"type":"integer","minimum":1,"maximum":10,"default":1},"addons":{"type":"object","description":"Options for a domain, each true or absent. Only the options this deployment offers are kept; privacy only where the registry takes it.","properties":{"privacy":{"type":"boolean"},"premiumDns":{"type":"boolean"},"spamExperts":{"type":"boolean"},"easyDmarc":{"type":"boolean"}}}}},"description":"Absent: the account's saved basket"},"registrant":{"type":"object","required":["firstname","lastname","address","postal","city","country","phone","email"],"properties":{"firstname":{"type":"string"},"lastname":{"type":"string"},"company":{"type":"string"},"address":{"type":"string"},"postal":{"type":"string","maxLength":16,"description":"Its shape is checked for the countries that use one, for example 75001 in FR"},"city":{"type":"string"},"country":{"type":"string","pattern":"^[A-Za-z]{2}$","description":"ISO 3166-1 alpha-2 code of a country or territory, any case, for example FR (the United Kingdom is GB). Only codes ISO assigns are taken: not UK, EL, EU or XK. A TLD with a residence rule (.fr, .eu and others) needs an eligible country, see /terms#eligibility"},"phone":{"type":"string","maxLength":40,"description":"+<calling code>.<number>, for example +33.612345678. +33612345678, +33 6 12 34 56 78, 0033… or a national number of the registrant's country are converted to that format, and its length is checked per country."},"state":{"type":"string"},"email":{"type":"string","format":"email"}}},"turnstile":{"type":"string"},"waiver":{"type":"boolean","enum":[true]}}}}}},"responses":{"201":{"description":"Order created; pay at checkoutUrl","content":{"application/json":{"schema":{"type":"object","required":["orderId","kind","status","domain","years","lines","total","currency","statusUrl","policy"],"properties":{"orderId":{"type":"string"},"kind":{"type":"string","enum":["register","renew"],"description":"register: new domains; renew: years added to a domain of the account"},"status":{"type":"string","enum":["awaiting_payment","expired","paid","registering","registered","partly_failed","failed","refunded"],"description":"For a renewal, registered means renewed. The state is one of: awaiting_payment, expired, paid, registering, registered, partly_failed, failed, refunded. The final states: registered, partly_failed, failed, refunded, expired. partly_failed: some names were registered and the others were not; each line's status, and whether its refund is done or pending, is in lines[]."},"domain":{"type":"string","description":"The first line's domain; lines has them all"},"years":{"type":"integer","description":"The first line's years"},"lines":{"type":"array","items":{"type":"object","properties":{"lineId":{"type":"string"},"domain":{"type":"string"},"tld":{"type":"string"},"years":{"type":"integer"},"status":{"type":"string","enum":["pending","registering","registered","failed","refunded"]},"price":{"type":"number"},"renewPrice":{"type":["number","null"]},"addons":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"}}}},"addonsTotal":{"type":"number"},"total":{"type":"number","description":"The line, in the order's currency before VAT"},"registeredAt":{"type":["string","null"]},"heldUntil":{"type":["string","null"],"format":"date-time","description":"Set while the line waits for a registrar top-up. After this time, no new attempt is made: the line fails and a refund is started. The line status stays pending or registering meanwhile."},"failureReason":{"type":["string","null"]},"refunded":{"type":["number","null"],"description":"What came back for this line, VAT included"},"creditNote":{"type":["object","null"],"description":"The credit note that refunded this line","properties":{"number":{"type":["string","null"]},"url":{"type":"string","description":"Opens the credit note: GET /api/orders/{id}/credit-notes/{lineId}, with the order's view token"}}}}}},"total":{"type":"number","description":"In currency before VAT: the sum of the lines. A line: the first-year price, plus the larger of the first-year and renewal price for each extra year, plus its options per year. A renewal: the renewal price times the years, plus the options."},"currency":{"type":"string","enum":["USD","EUR"]},"checkoutUrl":{"type":["string","null"],"description":"Give this link to the human to pay. Present while the quote can be paid; null once it lapsed or closed. Nothing is charged until they pay."},"statusUrl":{"type":"string"},"expiresAt":{"type":"string","format":"date-time","description":"When the quote and its payment link expire"},"createdAt":{"type":"string","format":"date-time"},"registeredAt":{"type":["string","null"],"description":"When the last domain of the order was registered (or renewed); null when no domain was registered"},"failureReason":{"type":["string","null"]},"policy":{"type":"object"},"charged":{"type":["object","null"],"description":"What the buyer paid, VAT included. Null before payment, and for orders paid before amounts were recorded.","properties":{"total":{"type":"number"},"vat":{"type":"number"},"currency":{"type":"string","enum":["USD","EUR"]},"vatNote":{"type":["string","null"],"description":"Set on a reverse-charge sale"}}},"refunds":{"type":["object","null"],"description":"What went back to the card, VAT included: refunds made by us or by hand in Stripe, counted once each. A refund that failed does not count. Null when nothing was refunded. A refund never changes the order's status.","properties":{"total":{"type":"number","description":"Refunded and done"},"full":{"type":"boolean","description":"true when total reaches what was charged"},"pending":{"type":"number","description":"On its way to the card; 0 when none"}}},"invoice":{"type":["object","null"],"description":"Once the payment provider issued it. url opens it for the account (key or session); it carries the order's view token.","properties":{"number":{"type":["string","null"]},"url":{"type":"string"},"test":{"type":"boolean","description":"A test payment's invoice, not a tax document"}}}}}}}},"400":{"description":"Bad lines, registrant, or period; an empty basket; or a registrant country that the TLD's residence rule refuses (see /terms#eligibility; issues[0].path: [\"registrant\", \"country\"]), or a name too short for the TLD's naming rule (see /terms#eligibility)"},"401":{"description":"Not signed in"},"403":{"description":"Turnstile check failed"},"429":{"description":"Too many orders from this network"},"501":{"description":"Web checkout not open on this deployment"}}}},"/api/account/basket":{"get":{"operationId":"get_basket","security":[{"session":[]}],"responses":{"200":{"description":"The basket, priced live","content":{"application/json":{"schema":{"type":"object","properties":{"lines":{"type":"array","items":{"type":"object","properties":{"domain":{"type":"string"},"tld":{"type":"string"},"years":{"type":"integer"},"minYears":{"type":"integer"},"maxYears":{"type":"integer"},"price":{"type":"number","description":"The first year, in currency before VAT"},"renewPrice":{"type":"number"},"domainTotal":{"type":"number"},"addons":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"price":{"type":"number"},"on":{"type":"boolean"},"available":{"type":"boolean"}}}},"addonsTotal":{"type":"number"},"lineTotal":{"type":"number"},"renewsAt":{"type":"string","format":"date"}}}},"subtotal":{"type":"number","description":"In currency before VAT"},"currency":{"type":"string","enum":["USD","EUR"]},"problems":{"type":"array","items":{"type":"object","properties":{"domain":{"type":"string"},"error":{"type":"string"}}}}}}}}},"401":{"description":"Not signed in","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}},"put":{"operationId":"set_basket","description":"Replaces the basket. With merge: true, the lines join the saved ones instead (the browser's basket after sign-in), together with the lines of an emailed sign-in link whose save failed; a line sent here wins a name both hold.","security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["lines"],"properties":{"lines":{"type":"array","items":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string"},"years":{"type":"integer","minimum":1,"maximum":10,"default":1},"addons":{"type":"object","description":"Options for a domain, each true or absent. Only the options this deployment offers are kept; privacy only where the registry takes it.","properties":{"privacy":{"type":"boolean"},"premiumDns":{"type":"boolean"},"spamExperts":{"type":"boolean"},"easyDmarc":{"type":"boolean"}}}}},"maxItems":20},"merge":{"type":"boolean"}}}}}},"responses":{"200":{"description":"The basket, priced live","content":{"application/json":{"schema":{"type":"object","properties":{"lines":{"type":"array","items":{"type":"object","properties":{"domain":{"type":"string"},"tld":{"type":"string"},"years":{"type":"integer"},"minYears":{"type":"integer"},"maxYears":{"type":"integer"},"price":{"type":"number","description":"The first year, in currency before VAT"},"renewPrice":{"type":"number"},"domainTotal":{"type":"number"},"addons":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"price":{"type":"number"},"on":{"type":"boolean"},"available":{"type":"boolean"}}}},"addonsTotal":{"type":"number"},"lineTotal":{"type":"number"},"renewsAt":{"type":"string","format":"date"}}}},"subtotal":{"type":"number","description":"In currency before VAT"},"currency":{"type":"string","enum":["USD","EUR"]},"problems":{"type":"array","items":{"type":"object","properties":{"domain":{"type":"string"},"error":{"type":"string"}}}}}}}}},"400":{"description":"Bad lines","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"401":{"description":"Not signed in","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}},"delete":{"operationId":"clear_basket","security":[{"session":[]}],"responses":{"200":{"description":"The empty basket","content":{"application/json":{"schema":{"type":"object","properties":{"lines":{"type":"array","items":{"type":"object","properties":{"domain":{"type":"string"},"tld":{"type":"string"},"years":{"type":"integer"},"minYears":{"type":"integer"},"maxYears":{"type":"integer"},"price":{"type":"number","description":"The first year, in currency before VAT"},"renewPrice":{"type":"number"},"domainTotal":{"type":"number"},"addons":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"price":{"type":"number"},"on":{"type":"boolean"},"available":{"type":"boolean"}}}},"addonsTotal":{"type":"number"},"lineTotal":{"type":"number"},"renewsAt":{"type":"string","format":"date"}}}},"subtotal":{"type":"number","description":"In currency before VAT"},"currency":{"type":"string","enum":["USD","EUR"]},"problems":{"type":"array","items":{"type":"object","properties":{"domain":{"type":"string"},"error":{"type":"string"}}}}}}}}},"401":{"description":"Not signed in","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/basket/price":{"post":{"operationId":"price_basket","description":"Prices basket lines without saving them, for a visitor who has not signed in. Same answer as get_basket.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["lines"],"properties":{"lines":{"type":"array","items":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string"},"years":{"type":"integer","minimum":1,"maximum":10,"default":1},"addons":{"type":"object","description":"Options for a domain, each true or absent. Only the options this deployment offers are kept; privacy only where the registry takes it.","properties":{"privacy":{"type":"boolean"},"premiumDns":{"type":"boolean"},"spamExperts":{"type":"boolean"},"easyDmarc":{"type":"boolean"}}}}},"maxItems":20}}}}}},"responses":{"200":{"description":"The lines, priced live","content":{"application/json":{"schema":{"type":"object","properties":{"lines":{"type":"array","items":{"type":"object","properties":{"domain":{"type":"string"},"tld":{"type":"string"},"years":{"type":"integer"},"minYears":{"type":"integer"},"maxYears":{"type":"integer"},"price":{"type":"number","description":"The first year, in currency before VAT"},"renewPrice":{"type":"number"},"domainTotal":{"type":"number"},"addons":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"price":{"type":"number"},"on":{"type":"boolean"},"available":{"type":"boolean"}}}},"addonsTotal":{"type":"number"},"lineTotal":{"type":"number"},"renewsAt":{"type":"string","format":"date"}}}},"subtotal":{"type":"number","description":"In currency before VAT"},"currency":{"type":"string","enum":["USD","EUR"]},"problems":{"type":"array","items":{"type":"object","properties":{"domain":{"type":"string"},"error":{"type":"string"}}}}}}}}},"400":{"description":"Bad lines","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/basket/checkout":{"post":{"operationId":"checkout_basket","description":"One order and one payment link for the whole basket: the lines given, or the account's saved basket, every domain to the same registrant. Give checkoutUrl to the human to pay; nothing is charged until they pay. A line that fails after payment is refunded alone. Payment clears the saved basket only when its domain names match the paid order; a basket changed after checkout stays. A retried call, or any key or connection of the account, gets the same open order for the same lines and registrant. A new order closes the older open ones for the same names. A signed-in session must send waiver: true; with a key, the human accepts the withdrawal waiver on the payment page.","security":[{"bearer":[]},{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["registrant"],"properties":{"lines":{"type":"array","items":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string"},"years":{"type":"integer","minimum":1,"maximum":10,"default":1},"addons":{"type":"object","description":"Options for a domain, each true or absent. Only the options this deployment offers are kept; privacy only where the registry takes it.","properties":{"privacy":{"type":"boolean"},"premiumDns":{"type":"boolean"},"spamExperts":{"type":"boolean"},"easyDmarc":{"type":"boolean"}}}}},"maxItems":20},"registrant":{"type":"object","required":["firstname","lastname","address","postal","city","country","phone","email"],"properties":{"firstname":{"type":"string"},"lastname":{"type":"string"},"company":{"type":"string"},"address":{"type":"string"},"postal":{"type":"string","maxLength":16,"description":"Its shape is checked for the countries that use one, for example 75001 in FR"},"city":{"type":"string"},"country":{"type":"string","pattern":"^[A-Za-z]{2}$","description":"ISO 3166-1 alpha-2 code of a country or territory, any case, for example FR (the United Kingdom is GB). Only codes ISO assigns are taken: not UK, EL, EU or XK. A TLD with a residence rule (.fr, .eu and others) needs an eligible country, see /terms#eligibility"},"phone":{"type":"string","maxLength":40,"description":"+<calling code>.<number>, for example +33.612345678. +33612345678, +33 6 12 34 56 78, 0033… or a national number of the registrant's country are converted to that format, and its length is checked per country."},"state":{"type":"string"},"email":{"type":"string","format":"email"}}},"waiver":{"type":"boolean","description":"Session callers only: the buyer ticked the withdrawal waiver. Required with a session; ignored with a key."}}}}}},"responses":{"201":{"description":"Order created; pay at checkoutUrl","content":{"application/json":{"schema":{"type":"object","required":["orderId","kind","status","domain","years","lines","total","currency","statusUrl","policy"],"properties":{"orderId":{"type":"string"},"kind":{"type":"string","enum":["register","renew"],"description":"register: new domains; renew: years added to a domain of the account"},"status":{"type":"string","enum":["awaiting_payment","expired","paid","registering","registered","partly_failed","failed","refunded"],"description":"For a renewal, registered means renewed. The state is one of: awaiting_payment, expired, paid, registering, registered, partly_failed, failed, refunded. The final states: registered, partly_failed, failed, refunded, expired. partly_failed: some names were registered and the others were not; each line's status, and whether its refund is done or pending, is in lines[]."},"domain":{"type":"string","description":"The first line's domain; lines has them all"},"years":{"type":"integer","description":"The first line's years"},"lines":{"type":"array","items":{"type":"object","properties":{"lineId":{"type":"string"},"domain":{"type":"string"},"tld":{"type":"string"},"years":{"type":"integer"},"status":{"type":"string","enum":["pending","registering","registered","failed","refunded"]},"price":{"type":"number"},"renewPrice":{"type":["number","null"]},"addons":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"}}}},"addonsTotal":{"type":"number"},"total":{"type":"number","description":"The line, in the order's currency before VAT"},"registeredAt":{"type":["string","null"]},"heldUntil":{"type":["string","null"],"format":"date-time","description":"Set while the line waits for a registrar top-up. After this time, no new attempt is made: the line fails and a refund is started. The line status stays pending or registering meanwhile."},"failureReason":{"type":["string","null"]},"refunded":{"type":["number","null"],"description":"What came back for this line, VAT included"},"creditNote":{"type":["object","null"],"description":"The credit note that refunded this line","properties":{"number":{"type":["string","null"]},"url":{"type":"string","description":"Opens the credit note: GET /api/orders/{id}/credit-notes/{lineId}, with the order's view token"}}}}}},"total":{"type":"number","description":"In currency before VAT: the sum of the lines. A line: the first-year price, plus the larger of the first-year and renewal price for each extra year, plus its options per year. A renewal: the renewal price times the years, plus the options."},"currency":{"type":"string","enum":["USD","EUR"]},"checkoutUrl":{"type":["string","null"],"description":"Give this link to the human to pay. Present while the quote can be paid; null once it lapsed or closed. Nothing is charged until they pay."},"statusUrl":{"type":"string"},"expiresAt":{"type":"string","format":"date-time","description":"When the quote and its payment link expire"},"createdAt":{"type":"string","format":"date-time"},"registeredAt":{"type":["string","null"],"description":"When the last domain of the order was registered (or renewed); null when no domain was registered"},"failureReason":{"type":["string","null"]},"policy":{"type":"object"},"charged":{"type":["object","null"],"description":"What the buyer paid, VAT included. Null before payment, and for orders paid before amounts were recorded.","properties":{"total":{"type":"number"},"vat":{"type":"number"},"currency":{"type":"string","enum":["USD","EUR"]},"vatNote":{"type":["string","null"],"description":"Set on a reverse-charge sale"}}},"refunds":{"type":["object","null"],"description":"What went back to the card, VAT included: refunds made by us or by hand in Stripe, counted once each. A refund that failed does not count. Null when nothing was refunded. A refund never changes the order's status.","properties":{"total":{"type":"number","description":"Refunded and done"},"full":{"type":"boolean","description":"true when total reaches what was charged"},"pending":{"type":"number","description":"On its way to the card; 0 when none"}}},"invoice":{"type":["object","null"],"description":"Once the payment provider issued it. url opens it for the account (key or session); it carries the order's view token.","properties":{"number":{"type":["string","null"]},"url":{"type":"string"},"test":{"type":"boolean","description":"A test payment's invoice, not a tax document"}}}}}}}},"400":{"description":"Bad lines or registrant, a taken name, an empty basket, a session without the waiver, or a registrant country that the TLD's residence rule refuses (see /terms#eligibility; field: registrant.country), or a name too short for the TLD's naming rule (see /terms#eligibility)","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"401":{"description":"No key or session","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/domains":{"get":{"operationId":"list_domains","security":[{"bearer":[]},{"session":[]}],"responses":{"200":{"description":"The account's domains","content":{"application/json":{"schema":{"type":"object","properties":{"domains":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"state":{"type":"string"},"expiresAt":{"type":["string","null"]},"daysLeft":{"type":["integer","null"],"description":"Whole UTC days to expiry, negative once expired"},"autoRenew":{"type":"boolean","description":"Off by default. On: we charge the saved card 7 days before expiry, then renew (PUT /api/domains/{name}/auto-renew)"},"orderId":{"type":"string"},"registeredAt":{"type":"string"},"renewPrice":{"type":["number","null"],"description":"Today's price for one year of renewal with the domain's options, in USD before VAT: what the auto-renew charge takes. The charge uses the price on the charge day, so this can still change; VAT is added at the charge. Null when the price list does not answer."},"registrant":{"type":["string","null"]}}}}}}}}},"401":{"description":"No key or session"}}}},"/api/orders":{"get":{"operationId":"list_orders","security":[{"bearer":[]},{"session":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"The account's orders, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"orders":{"type":"array","items":{"type":"object","required":["orderId","kind","status","domain","years","lines","total","currency","statusUrl","policy"],"properties":{"orderId":{"type":"string"},"kind":{"type":"string","enum":["register","renew"],"description":"register: new domains; renew: years added to a domain of the account"},"status":{"type":"string","enum":["awaiting_payment","expired","paid","registering","registered","partly_failed","failed","refunded"],"description":"For a renewal, registered means renewed. The state is one of: awaiting_payment, expired, paid, registering, registered, partly_failed, failed, refunded. The final states: registered, partly_failed, failed, refunded, expired. partly_failed: some names were registered and the others were not; each line's status, and whether its refund is done or pending, is in lines[]."},"domain":{"type":"string","description":"The first line's domain; lines has them all"},"years":{"type":"integer","description":"The first line's years"},"lines":{"type":"array","items":{"type":"object","properties":{"lineId":{"type":"string"},"domain":{"type":"string"},"tld":{"type":"string"},"years":{"type":"integer"},"status":{"type":"string","enum":["pending","registering","registered","failed","refunded"]},"price":{"type":"number"},"renewPrice":{"type":["number","null"]},"addons":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"}}}},"addonsTotal":{"type":"number"},"total":{"type":"number","description":"The line, in the order's currency before VAT"},"registeredAt":{"type":["string","null"]},"heldUntil":{"type":["string","null"],"format":"date-time","description":"Set while the line waits for a registrar top-up. After this time, no new attempt is made: the line fails and a refund is started. The line status stays pending or registering meanwhile."},"failureReason":{"type":["string","null"]},"refunded":{"type":["number","null"],"description":"What came back for this line, VAT included"},"creditNote":{"type":["object","null"],"description":"The credit note that refunded this line","properties":{"number":{"type":["string","null"]},"url":{"type":"string","description":"Opens the credit note: GET /api/orders/{id}/credit-notes/{lineId}, with the order's view token"}}}}}},"total":{"type":"number","description":"In currency before VAT: the sum of the lines. A line: the first-year price, plus the larger of the first-year and renewal price for each extra year, plus its options per year. A renewal: the renewal price times the years, plus the options."},"currency":{"type":"string","enum":["USD","EUR"]},"checkoutUrl":{"type":["string","null"],"description":"Give this link to the human to pay. Present while the quote can be paid; null once it lapsed or closed. Nothing is charged until they pay."},"statusUrl":{"type":"string"},"expiresAt":{"type":"string","format":"date-time","description":"When the quote and its payment link expire"},"createdAt":{"type":"string","format":"date-time"},"registeredAt":{"type":["string","null"],"description":"When the last domain of the order was registered (or renewed); null when no domain was registered"},"failureReason":{"type":["string","null"]},"policy":{"type":"object"},"charged":{"type":["object","null"],"description":"What the buyer paid, VAT included. Null before payment, and for orders paid before amounts were recorded.","properties":{"total":{"type":"number"},"vat":{"type":"number"},"currency":{"type":"string","enum":["USD","EUR"]},"vatNote":{"type":["string","null"],"description":"Set on a reverse-charge sale"}}},"refunds":{"type":["object","null"],"description":"What went back to the card, VAT included: refunds made by us or by hand in Stripe, counted once each. A refund that failed does not count. Null when nothing was refunded. A refund never changes the order's status.","properties":{"total":{"type":"number","description":"Refunded and done"},"full":{"type":"boolean","description":"true when total reaches what was charged"},"pending":{"type":"number","description":"On its way to the card; 0 when none"}}},"invoice":{"type":["object","null"],"description":"Once the payment provider issued it. url opens it for the account (key or session); it carries the order's view token.","properties":{"number":{"type":["string","null"]},"url":{"type":"string"},"test":{"type":"boolean","description":"A test payment's invoice, not a tax document"}}}}}}}}}}},"400":{"description":"Bad limit"},"401":{"description":"No key or session"}}}},"/api/orders/{id}":{"get":{"operationId":"get_order","security":[{"bearer":[]},{"session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"t","in":"query","required":false,"schema":{"type":"string"},"description":"View token from statusUrl, instead of a key"}],"responses":{"200":{"description":"Order","content":{"application/json":{"schema":{"type":"object","required":["orderId","kind","status","domain","years","lines","total","currency","statusUrl","policy"],"properties":{"orderId":{"type":"string"},"kind":{"type":"string","enum":["register","renew"],"description":"register: new domains; renew: years added to a domain of the account"},"status":{"type":"string","enum":["awaiting_payment","expired","paid","registering","registered","partly_failed","failed","refunded"],"description":"For a renewal, registered means renewed. The state is one of: awaiting_payment, expired, paid, registering, registered, partly_failed, failed, refunded. The final states: registered, partly_failed, failed, refunded, expired. partly_failed: some names were registered and the others were not; each line's status, and whether its refund is done or pending, is in lines[]."},"domain":{"type":"string","description":"The first line's domain; lines has them all"},"years":{"type":"integer","description":"The first line's years"},"lines":{"type":"array","items":{"type":"object","properties":{"lineId":{"type":"string"},"domain":{"type":"string"},"tld":{"type":"string"},"years":{"type":"integer"},"status":{"type":"string","enum":["pending","registering","registered","failed","refunded"]},"price":{"type":"number"},"renewPrice":{"type":["number","null"]},"addons":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"}}}},"addonsTotal":{"type":"number"},"total":{"type":"number","description":"The line, in the order's currency before VAT"},"registeredAt":{"type":["string","null"]},"heldUntil":{"type":["string","null"],"format":"date-time","description":"Set while the line waits for a registrar top-up. After this time, no new attempt is made: the line fails and a refund is started. The line status stays pending or registering meanwhile."},"failureReason":{"type":["string","null"]},"refunded":{"type":["number","null"],"description":"What came back for this line, VAT included"},"creditNote":{"type":["object","null"],"description":"The credit note that refunded this line","properties":{"number":{"type":["string","null"]},"url":{"type":"string","description":"Opens the credit note: GET /api/orders/{id}/credit-notes/{lineId}, with the order's view token"}}}}}},"total":{"type":"number","description":"In currency before VAT: the sum of the lines. A line: the first-year price, plus the larger of the first-year and renewal price for each extra year, plus its options per year. A renewal: the renewal price times the years, plus the options."},"currency":{"type":"string","enum":["USD","EUR"]},"checkoutUrl":{"type":["string","null"],"description":"Give this link to the human to pay. Present while the quote can be paid; null once it lapsed or closed. Nothing is charged until they pay."},"statusUrl":{"type":"string"},"expiresAt":{"type":"string","format":"date-time","description":"When the quote and its payment link expire"},"createdAt":{"type":"string","format":"date-time"},"registeredAt":{"type":["string","null"],"description":"When the last domain of the order was registered (or renewed); null when no domain was registered"},"failureReason":{"type":["string","null"]},"policy":{"type":"object"},"charged":{"type":["object","null"],"description":"What the buyer paid, VAT included. Null before payment, and for orders paid before amounts were recorded.","properties":{"total":{"type":"number"},"vat":{"type":"number"},"currency":{"type":"string","enum":["USD","EUR"]},"vatNote":{"type":["string","null"],"description":"Set on a reverse-charge sale"}}},"refunds":{"type":["object","null"],"description":"What went back to the card, VAT included: refunds made by us or by hand in Stripe, counted once each. A refund that failed does not count. Null when nothing was refunded. A refund never changes the order's status.","properties":{"total":{"type":"number","description":"Refunded and done"},"full":{"type":"boolean","description":"true when total reaches what was charged"},"pending":{"type":"number","description":"On its way to the card; 0 when none"}}},"invoice":{"type":["object","null"],"description":"Once the payment provider issued it. url opens it for the account (key or session); it carries the order's view token.","properties":{"number":{"type":["string","null"]},"url":{"type":"string"},"test":{"type":"boolean","description":"A test payment's invoice, not a tax document"}}}}}}}},"401":{"description":"No key or token"},"404":{"description":"Not found"}}}},"/api/orders/{id}/invoice":{"get":{"operationId":"get_invoice","description":"The invoice of a paid order. A browser is redirected (302) to the PDF, or with ?view=online to the hosted page. Send Accept: application/json for the links instead. The provider's links expire: ask again rather than storing them.","security":[{"bearer":[]},{"session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"t","in":"query","required":false,"schema":{"type":"string"},"description":"View token from statusUrl, instead of a key"},{"name":"view","in":"query","required":false,"schema":{"type":"string","enum":["online"]},"description":"Redirect to the hosted invoice page instead of the PDF"}],"responses":{"200":{"description":"With Accept: application/json","content":{"application/json":{"schema":{"type":"object","required":["orderId","test"],"properties":{"orderId":{"type":"string"},"number":{"type":["string","null"]},"test":{"type":"boolean"},"pdfUrl":{"type":["string","null"]},"hostedUrl":{"type":["string","null"]}}}}}},"302":{"description":"To the PDF or the hosted page"},"404":{"description":"No such order for this caller, or no invoice yet (before payment, or a minute after it)","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/orders/{id}/credit-notes/{lineId}":{"get":{"operationId":"get_credit_note","description":"The credit note that refunded one line of an order. A browser is redirected (302) to its PDF; a test note goes to its row on the test invoice page. Send Accept: application/json for the link instead. The provider's links expire: ask again rather than storing them.","security":[{"bearer":[]},{"session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"lineId","in":"path","required":true,"schema":{"type":"string"}},{"name":"t","in":"query","required":false,"schema":{"type":"string"},"description":"View token from statusUrl, instead of a key"}],"responses":{"200":{"description":"With Accept: application/json","content":{"application/json":{"schema":{"type":"object","required":["orderId","lineId","test"],"properties":{"orderId":{"type":"string"},"lineId":{"type":"string"},"number":{"type":["string","null"]},"test":{"type":"boolean"},"pdfUrl":{"type":["string","null"],"description":"null for a test note"}}}}}},"302":{"description":"To the PDF, or to the test invoice page"},"404":{"description":"No such order for this caller, no such line in it, or no credit note for the line","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"502":{"description":"The payment provider did not answer","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"503":{"description":"The credit note has no document yet","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/domains/{name}":{"get":{"operationId":"get_domain","security":[{"bearer":[]},{"session":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"responses":{"200":{"description":"The domain with the registrar's live facts","content":{"application/json":{"schema":{"type":"object","required":["name","state","autoRenew","autoRenewAvailable","autoRenewBlocked","renewBlocked","managed","info","infoError"],"properties":{"name":{"type":"string"},"state":{"type":"string"},"expiresAt":{"type":["string","null"]},"autoRenew":{"type":"boolean","description":"Off by default. On: we charge the saved card 7 days before expiry (retries at 3 and 1 day before after a refused or missing card; no new charge after a paid renewal that failed), renew at the registrar once the payment is in, and email a payment link if the charge fails. POST /api/domains/{name}/renew works either way."},"autoRenewAvailable":{"type":"boolean","description":"Whether PUT /api/domains/{name}/auto-renew can turn auto-renew on now"},"autoRenewBlocked":{"type":["string","null"],"description":"Why it cannot, in plain words; null when it can"},"renewBlocked":{"type":["string","null"],"description":"Why the domain cannot be renewed: its registrant's country cannot hold the .fr or .eu name. Ends with the next step. null when it may renew. While it is set, POST /api/domains/{name}/renew answers 400 (field: registrant.country)."},"registrarRef":{"type":"string"},"managed":{"type":"boolean","description":"false: the domain's registrar is not connected here. Nothing can change here, info is null, and renewal goes through support (autoRenewBlocked says so)."},"info":{"type":["object","null"],"description":"The registrar's live facts; null when it did not answer (see infoError)","properties":{"status":{"type":"string","enum":["active","pending"]},"expiresAt":{"type":["string","null"]},"nameservers":{"type":"object","properties":{"ours":{"type":"boolean","description":"On our nameservers: DNS records apply"},"hosts":{"type":"array","items":{"type":"string"}}}},"locked":{"type":"boolean"},"lockable":{"type":"boolean","description":"Whether the registry allows a transfer lock"},"dnssec":{"type":"boolean"},"canRenew":{"type":"boolean"},"privacyAllowed":{"type":"boolean"},"privacyOn":{"type":"boolean"}}},"infoError":{"type":["string","null"]}}}}}},"401":{"description":"No key or session","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/domains/{name}/renew":{"post":{"operationId":"renew_domain","description":"Opens a renewal order at today's renewal price. Give checkoutUrl to the human to pay: nothing is charged and nothing is renewed until they pay. A retried call answers the same open order.","security":[{"bearer":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"years":{"type":"integer","minimum":1,"maximum":10,"default":1,"description":"Years to add, 1 to 10. The domain must stay at most 10 years ahead of today, so a domain with years left takes fewer. 1 by default."},"addons":{"type":"object","description":"The options to keep with the renewal. Absent: the domain keeps its current options; {}: drops them all.","properties":{"privacy":{"type":"boolean"},"premiumDns":{"type":"boolean"},"spamExperts":{"type":"boolean"},"easyDmarc":{"type":"boolean"}}}}}}}},"responses":{"201":{"description":"Order created; pay at checkoutUrl","content":{"application/json":{"schema":{"type":"object","required":["orderId","kind","status","domain","years","lines","total","currency","statusUrl","policy"],"properties":{"orderId":{"type":"string"},"kind":{"type":"string","enum":["register","renew"],"description":"register: new domains; renew: years added to a domain of the account"},"status":{"type":"string","enum":["awaiting_payment","expired","paid","registering","registered","partly_failed","failed","refunded"],"description":"For a renewal, registered means renewed. The state is one of: awaiting_payment, expired, paid, registering, registered, partly_failed, failed, refunded. The final states: registered, partly_failed, failed, refunded, expired. partly_failed: some names were registered and the others were not; each line's status, and whether its refund is done or pending, is in lines[]."},"domain":{"type":"string","description":"The first line's domain; lines has them all"},"years":{"type":"integer","description":"The first line's years"},"lines":{"type":"array","items":{"type":"object","properties":{"lineId":{"type":"string"},"domain":{"type":"string"},"tld":{"type":"string"},"years":{"type":"integer"},"status":{"type":"string","enum":["pending","registering","registered","failed","refunded"]},"price":{"type":"number"},"renewPrice":{"type":["number","null"]},"addons":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"}}}},"addonsTotal":{"type":"number"},"total":{"type":"number","description":"The line, in the order's currency before VAT"},"registeredAt":{"type":["string","null"]},"heldUntil":{"type":["string","null"],"format":"date-time","description":"Set while the line waits for a registrar top-up. After this time, no new attempt is made: the line fails and a refund is started. The line status stays pending or registering meanwhile."},"failureReason":{"type":["string","null"]},"refunded":{"type":["number","null"],"description":"What came back for this line, VAT included"},"creditNote":{"type":["object","null"],"description":"The credit note that refunded this line","properties":{"number":{"type":["string","null"]},"url":{"type":"string","description":"Opens the credit note: GET /api/orders/{id}/credit-notes/{lineId}, with the order's view token"}}}}}},"total":{"type":"number","description":"In currency before VAT: the sum of the lines. A line: the first-year price, plus the larger of the first-year and renewal price for each extra year, plus its options per year. A renewal: the renewal price times the years, plus the options."},"currency":{"type":"string","enum":["USD","EUR"]},"checkoutUrl":{"type":["string","null"],"description":"Give this link to the human to pay. Present while the quote can be paid; null once it lapsed or closed. Nothing is charged until they pay."},"statusUrl":{"type":"string"},"expiresAt":{"type":"string","format":"date-time","description":"When the quote and its payment link expire"},"createdAt":{"type":"string","format":"date-time"},"registeredAt":{"type":["string","null"],"description":"When the last domain of the order was registered (or renewed); null when no domain was registered"},"failureReason":{"type":["string","null"]},"policy":{"type":"object"},"charged":{"type":["object","null"],"description":"What the buyer paid, VAT included. Null before payment, and for orders paid before amounts were recorded.","properties":{"total":{"type":"number"},"vat":{"type":"number"},"currency":{"type":"string","enum":["USD","EUR"]},"vatNote":{"type":["string","null"],"description":"Set on a reverse-charge sale"}}},"refunds":{"type":["object","null"],"description":"What went back to the card, VAT included: refunds made by us or by hand in Stripe, counted once each. A refund that failed does not count. Null when nothing was refunded. A refund never changes the order's status.","properties":{"total":{"type":"number","description":"Refunded and done"},"full":{"type":"boolean","description":"true when total reaches what was charged"},"pending":{"type":"number","description":"On its way to the card; 0 when none"}}},"invoice":{"type":["object","null"],"description":"Once the payment provider issued it. url opens it for the account (key or session); it carries the order's view token.","properties":{"number":{"type":["string","null"]},"url":{"type":"string"},"test":{"type":"boolean","description":"A test payment's invoice, not a tax document"}}}}}}}},"400":{"description":"Bad period (more years than fit within 10 years of today), not a domain of this account, or a renewal already paid; or a registrant country that cannot hold the .fr or .eu name (field: registrant.country)","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"401":{"description":"Missing or revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/domains/{name}/dns":{"get":{"operationId":"list_dns_records","description":"The zone's records, served while the domain is on our nameservers (ours). The zone's own SOA and NS are not listed.","security":[{"bearer":[]},{"session":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"responses":{"200":{"description":"The zone","content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"type":"string"},"ours":{"type":["boolean","null"],"description":"true on our nameservers, where these records are served; false on other nameservers; null when the registrar did not answer the nameserver read"},"records":{"type":"array","items":{"type":"object","required":["id","name","fqdn","type","value","ttl"],"properties":{"id":{"type":"string","description":"Stable while name, type, value and prio stay the same"},"name":{"type":"string"},"fqdn":{"type":"string"},"type":{"type":"string","enum":["A","AAAA","CNAME","MX","TXT","CAA","SRV","NS"]},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}}}}}}}},"401":{"description":"No key or session","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"409":{"description":"Managed outside this service","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"502":{"description":"Our registrar did not answer","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}},"post":{"operationId":"add_dns_record","security":[{"bearer":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type","value"],"properties":{"name":{"type":"string","default":"","description":"Host name inside the domain: \"\" or \"@\" for the domain itself, \"www\" for www.<domain>, \"*\" for a wildcard"},"type":{"type":"string","enum":["A","AAAA","CNAME","MX","TXT","CAA","SRV","NS"],"description":"NS is refused with 400: to move the whole domain to other nameservers, use PUT /api/domains/{name}/nameservers"},"value":{"type":"string","description":"An IP for A/AAAA, a host for CNAME/MX, text for TXT (without quotes)"},"ttl":{"type":"integer","minimum":600,"maximum":86400,"default":3600,"description":"Seconds, a whole number from 600 to 86400"},"prio":{"type":"integer","minimum":0,"maximum":65535,"description":"MX and SRV only; 10 by default"}}}}}},"responses":{"201":{"description":"The record, with its id","content":{"application/json":{"schema":{"type":"object","required":["id","name","fqdn","type","value","ttl"],"properties":{"id":{"type":"string","description":"Stable while name, type, value and prio stay the same"},"name":{"type":"string"},"fqdn":{"type":"string"},"type":{"type":"string","enum":["A","AAAA","CNAME","MX","TXT","CAA","SRV","NS"]},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}}}}},"400":{"description":"Invalid record, an NS record, or a TTL outside 600 to 86400","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"401":{"description":"Missing or revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"409":{"description":"Clashes with a record at the same name (CNAME) or already exists","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"502":{"description":"Our registrar did not answer, or the result could not be confirmed: list the records","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/domains/{name}/dns/{id}":{"put":{"operationId":"update_dns_record","description":"Removes the record, then adds the new one; puts the old one back if the add is refused. The answer is the record as the zone stores it.","security":[{"bearer":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"},{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^rec_[0-9a-f]{16}$"},"description":"The record's id from GET /api/domains/{name}/dns"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type","value"],"properties":{"name":{"type":"string","default":"","description":"Host name inside the domain: \"\" or \"@\" for the domain itself, \"www\" for www.<domain>, \"*\" for a wildcard"},"type":{"type":"string","enum":["A","AAAA","CNAME","MX","TXT","CAA","SRV","NS"],"description":"NS is refused with 400: to move the whole domain to other nameservers, use PUT /api/domains/{name}/nameservers"},"value":{"type":"string","description":"An IP for A/AAAA, a host for CNAME/MX, text for TXT (without quotes)"},"ttl":{"type":"integer","minimum":600,"maximum":86400,"default":3600,"description":"Seconds, a whole number from 600 to 86400"},"prio":{"type":"integer","minimum":0,"maximum":65535,"description":"MX and SRV only; 10 by default"}}}}}},"responses":{"200":{"description":"The new record","content":{"application/json":{"schema":{"type":"object","required":["id","name","fqdn","type","value","ttl"],"properties":{"id":{"type":"string","description":"Stable while name, type, value and prio stay the same"},"name":{"type":"string"},"fqdn":{"type":"string"},"type":{"type":"string","enum":["A","AAAA","CNAME","MX","TXT","CAA","SRV","NS"]},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}}}}},"400":{"description":"Invalid record, an NS record, or a TTL outside 600 to 86400","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"401":{"description":"Missing or revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"No such domain or record id: list again","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"409":{"description":"Clashes with a record at the same name (CNAME) or already exists","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"502":{"description":"Our registrar did not answer, or the registrar answered the remove but the record is still in the zone (code dns_record_not_removed; nothing changed, and the new record is not added), or the old record could not be put back (the error names it), or the result could not be confirmed: list the records","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"},"code":{"type":"string","enum":["dns_record_not_removed"],"description":"dns_record_not_removed: the registrar answered the remove, but the record is still in the zone. Nothing changed."}}}}}}}},"delete":{"operationId":"delete_dns_record","description":"Removes the record, then reads the zone to confirm it is gone.","security":[{"bearer":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"},{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^rec_[0-9a-f]{16}$"},"description":"The record's id from GET /api/domains/{name}/dns"}],"responses":{"200":{"description":"The removed record","content":{"application/json":{"schema":{"type":"object","properties":{"removed":{"type":"object","required":["id","name","fqdn","type","value","ttl"],"properties":{"id":{"type":"string","description":"Stable while name, type, value and prio stay the same"},"name":{"type":"string"},"fqdn":{"type":"string"},"type":{"type":"string","enum":["A","AAAA","CNAME","MX","TXT","CAA","SRV","NS"]},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}}}}}}},"401":{"description":"Missing or revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"No such domain or record id: list again","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"502":{"description":"Our registrar did not answer, or the registrar answered but the record is still in the zone (code dns_record_not_removed; nothing changed), or the result could not be confirmed: list the records","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"},"code":{"type":"string","enum":["dns_record_not_removed"],"description":"dns_record_not_removed: the registrar answered the remove, but the record is still in the zone. Nothing changed."}}}}}}}}},"/api/domains/{name}/nameservers":{"put":{"operationId":"set_nameservers","description":"Asks to change the nameservers: two to thirteen distinct host names (blanks and repeats are dropped first), or an empty list for our nameservers. A host inside the domain itself is refused: it needs a glue record, which this service cannot set. DNS records apply only on ours. Every change waits, the empty list too. It waits for the account owner: the answer is 202, we email them a link that works once, for 30 minutes, and nothing changes until they confirm it on /account/confirm, signed in to the same account. The same request while its link is open answers alreadySent: true and sends no new email. Revoking the key cancels its open requests. A newer request for the same domain replaces the open one. The 202 answer adds warnings for the hosts public DNS does not find; they never block the request.","security":[{"bearer":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["nameservers"],"properties":{"nameservers":{"type":"array","maxItems":26,"items":{"type":"string","maxLength":253},"description":"At most 13 once blanks and repeats are dropped"}}}}}},"responses":{"202":{"description":"Waits for the owner: we emailed the account owner a single-use link. Nothing changes until they confirm it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmationSent"}}}},"400":{"description":"One nameserver alone, more than 13, a repeat that leaves one, a bad host name, or a host inside the domain","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"401":{"description":"Missing or revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"409":{"description":"Managed outside this service","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"429":{"description":"5 confirmation requests for this account in the last hour; nothing changed","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"503":{"description":"We could not email the account owner; nothing changed","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/domains/{name}/cloudflare":{"put":{"operationId":"use_cloudflare","description":"Asks to move the domain to Cloudflare (Free plan): exactly the two nameservers Cloudflare assigned, each <label>.ns.cloudflare.com. Refused with 409 while DNSSEC is on at the registrar or a DS record still shows in public DNS; that answer adds dnssec_url, the dashboard page where the owner turns DNSSEC off, and PUT /api/domains/{name}/dnssec asks the owner for it. It waits for the account owner: the answer is 202, we email them a link that works once, for 30 minutes, and nothing changes until they confirm it on /account/confirm, signed in to the same account. The same request while its link is open answers alreadySent: true and sends no new email. Revoking the key cancels its open requests. A newer request for the same domain, here or on /nameservers, replaces the open one. The 202 answer adds warnings (hosts public DNS does not find) and recordWarnings (records that stop working unless they are in Cloudflare).","security":[{"bearer":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["nameservers"],"properties":{"nameservers":{"type":"array","maxItems":26,"items":{"type":"string","maxLength":253},"description":"Exactly two once blanks are dropped"}}}}}},"responses":{"202":{"description":"Waits for the owner: we emailed the account owner a single-use link. Nothing changes until they confirm it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmationSent"}}}},"400":{"description":"Not exactly two distinct Cloudflare nameservers","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"401":{"description":"Missing or revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"409":{"description":"Managed outside this service, DNSSEC still on (with dnssec_url), or a move already in progress","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"429":{"description":"5 confirmation requests for this account in the last hour; nothing changed","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"503":{"description":"We could not check DNSSEC, or could not email the account owner; nothing changed","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}},"get":{"operationId":"get_cloudflare_status","description":"Where the move to Cloudflare stands, from our records and public DNS only. Resolver caches can lag by hours: live means visible in public DNS.","security":[{"bearer":[]},{"session":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"responses":{"200":{"description":"The status","content":{"application/json":{"schema":{"type":"object","required":["domain","state","nameservers","seen","reason","requestedAt","checkedAt","settledAt","dnssec"],"properties":{"domain":{"type":"string"},"state":{"type":"string","enum":["none","pending","waiting","live","failed","replaced"],"description":"none: no move asked. pending: the registrar call is in flight or its outcome is being checked. waiting: the registrar took it; public DNS does not show it yet. live: public DNS shows the Cloudflare nameservers. failed: see reason; start a new move. replaced: a manual nameserver change replaced it."},"nameservers":{"type":"array","items":{"type":"string"},"description":"The two asked for; empty when none"},"seen":{"type":["array","null"],"items":{"type":"string"},"description":"The nameservers public DNS answered at the last check"},"reason":{"type":["string","null"],"description":"Why it failed or was replaced, or what is being checked; null otherwise"},"requestedAt":{"type":["string","null"],"format":"date-time"},"checkedAt":{"type":["string","null"],"format":"date-time"},"settledAt":{"type":["string","null"],"format":"date-time"},"dnssec":{"type":"object","properties":{"registrar":{"type":"string","enum":["on","off","unknown","not_read"],"description":"The registrar's DNSSEC setting; not_read on a status read, which never calls the registrar"},"publicDs":{"type":"string","enum":["published","absent","unknown"],"description":"Whether public DNS shows a DS record for the domain now; unknown once the move is live, failed or replaced, since a settled move reads no public DNS"}}}}}}}},"401":{"description":"No key or session","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"409":{"description":"Managed outside this service","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/cloudflare":{"put":{"operationId":"connect_cloudflare","description":"Links the owner's Cloudflare account for the one-click move: checks the token (active, one account or account_id, can read zones) and stores it encrypted. A Global API Key is refused. The account email hears of it. The answer never holds the token.","security":[{"bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string","maxLength":512,"description":"A Cloudflare API token with Zone: Read, Zone: Edit and DNS: Edit. Stored encrypted, never answered."},"account_id":{"type":"string","description":"The Cloudflare account, when the token sees several (the 400 answer lists them in accounts)"},"remember":{"type":"boolean","description":"Keep the link after the move is done (active, failed or cancelled). Absent with a token: the stored link's choice, else false."}}}}}},"responses":{"200":{"description":"The link","content":{"application/json":{"schema":{"type":"object","required":["connected","account","connectedAt","lastUsedAt","remember"],"properties":{"connected":{"type":"boolean"},"account":{"type":["object","null"],"properties":{"id":{"type":"string"},"name":{"type":["string","null"]}}},"connectedAt":{"type":["string","null"],"format":"date-time"},"lastUsedAt":{"type":["string","null"],"format":"date-time"},"remember":{"type":"boolean","description":"true: the link stays after a move is done; false: the token is deleted once a move is active, failed or cancelled"}}}}}},"400":{"description":"A bad, inactive or Global key, no zone read, or several accounts without account_id (the answer adds accounts)","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"401":{"description":"Missing or revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"409":{"description":"Another Cloudflare account while a move is open","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"501":{"description":"Linking Cloudflare is not set up here","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}},"get":{"operationId":"get_cloudflare_connection","description":"Whether a Cloudflare account is linked. Never the token.","security":[{"bearer":[]},{"session":[]}],"responses":{"200":{"description":"The link","content":{"application/json":{"schema":{"type":"object","required":["connected","account","connectedAt","lastUsedAt","remember"],"properties":{"connected":{"type":"boolean"},"account":{"type":["object","null"],"properties":{"id":{"type":"string"},"name":{"type":["string","null"]}}},"connectedAt":{"type":["string","null"],"format":"date-time"},"lastUsedAt":{"type":["string","null"],"format":"date-time"},"remember":{"type":"boolean","description":"true: the link stays after a move is done; false: the token is deleted once a move is active, failed or cancelled"}}}}}},"401":{"description":"No key or session","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"501":{"description":"Linking Cloudflare is not set up here","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}},"delete":{"operationId":"disconnect_cloudflare","description":"Deletes the stored token. Open moves are then followed in public DNS only. Delete the token in Cloudflare too.","security":[{"bearer":[]}],"responses":{"200":{"description":"Unlinked","content":{"application/json":{"schema":{"type":"object","properties":{"connected":{"type":"boolean","enum":[false]}}}}}},"401":{"description":"Missing or revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"501":{"description":"Linking Cloudflare is not set up here","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/domains/{name}/cloudflare-move":{"post":{"operationId":"prepare_cloudflare_move","description":"Creates the domain's zone on the linked Cloudflare account (Free plan), copies every record exactly (proxy off) and reads it back. Nameservers do not change: no email confirmation. A token in the body links Cloudflare first. A second call answers the open move and resumes a copy that stopped.","security":[{"bearer":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string","maxLength":512,"description":"A Cloudflare API token with Zone: Read, Zone: Edit and DNS: Edit. Stored encrypted, never answered."},"account_id":{"type":"string","description":"The Cloudflare account, when the token sees several (the 400 answer lists them in accounts)"},"remember":{"type":"boolean","description":"Keep the link after the move is done (active, failed or cancelled). Absent with a token: the stored link's choice, else false."}}}}}},"responses":{"200":{"description":"The move","content":{"application/json":{"schema":{"type":"object","required":["domain","connected","connectUrl","state","moveId","zoneStatus","reusedZone","nameservers","diff","reason","stale","done"],"properties":{"domain":{"type":"string"},"connected":{"type":"boolean","description":"A Cloudflare account is linked"},"connectUrl":{"type":"string","description":"The dashboard page that links Cloudflare"},"state":{"type":"string","enum":["none","preparing","prepared","switching","switched","unknown","cancelling","active","failed","cancelled"],"description":"preparing: the copy runs (stale: it stopped; prepare again resumes it). prepared: the copy is read back; switch next. switching: the nameserver change runs. unknown: we check whether the registrar took it. switched: waiting for Cloudflare. active: Cloudflare reports the zone active. failed: see reason. cancelled."},"moveId":{"type":["string","null"]},"zoneStatus":{"type":["string","null"],"enum":["pending","active",null]},"reusedZone":{"type":"boolean","description":"The zone was already in the Cloudflare account (pending)"},"nameservers":{"type":"array","items":{"type":"string"},"description":"The two Cloudflare assigned"},"diff":{"type":["object","null"],"description":"The last readback against the copy. The switch needs missing, different and extra empty.","properties":{"same":{"type":"integer"},"missing":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}}},"different":{"type":"array","items":{"type":"object","properties":{"want":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}},"got":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}}}}},"extra":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}}},"skipped":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"name":{"type":"string"}}}}}},"reason":{"type":["string","null"]},"stale":{"type":"boolean"},"done":{"type":"boolean","description":"Active at Cloudflare and visible in public DNS"},"preparedAt":{"type":["string","null"],"format":"date-time"},"switchedAt":{"type":["string","null"],"format":"date-time","description":"When the switch was asked for. Set while switching or unknown too: only state switched or active says the registrar took it"},"activeAt":{"type":["string","null"],"format":"date-time"},"publicDns":{"type":["object","null"],"description":"GET /api/domains/{name}/cloudflare, once the nameservers changed"}}}}}},"400":{"description":"A bad token in the body","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"401":{"description":"Missing or revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"409":{"description":"No link (with connect_url), not on our nameservers, a record type that cannot be copied, a zone already active or on another account, or managed outside this service","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"429":{"description":"Cloudflare asks to slow down","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"501":{"description":"Linking Cloudflare is not set up here","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"502":{"description":"Cloudflare refused or did not answer","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}},"put":{"operationId":"switch_cloudflare_move","description":"Asks to point the domain to the prepared zone's two Cloudflare nameservers. Every check answers at once and runs again at confirm time: prepared, records unchanged since the copy, an exact copy at Cloudflare, a pending zone with two nameservers, DNSSEC off (409 with dnssec_url). It waits for the account owner: the answer is 202, we email them a link that works once, for 30 minutes, and nothing changes until they confirm it on /account/confirm, signed in to the same account. The same request while its link is open answers alreadySent: true and sends no new email. Revoking the key cancels its open requests.","security":[{"bearer":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["moveId"],"properties":{"moveId":{"type":"string"}}}}}},"responses":{"202":{"description":"Waits for the owner: we emailed the account owner a single-use link. Nothing changes until they confirm it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmationSent"}}}},"400":{"description":"No moveId","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"401":{"description":"Missing or revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a move of this domain","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"409":{"description":"The records changed, the copy is not exact, DNSSEC is on, or the move is not prepared","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"429":{"description":"5 confirmation requests for this account in the last hour; nothing changed","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"503":{"description":"We could not email the account owner; nothing changed","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}},"get":{"operationId":"get_cloudflare_move","description":"Where the one-click move stands. Checks Cloudflare at most once a minute per move.","security":[{"bearer":[]},{"session":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"responses":{"200":{"description":"The move","content":{"application/json":{"schema":{"type":"object","required":["domain","connected","connectUrl","state","moveId","zoneStatus","reusedZone","nameservers","diff","reason","stale","done"],"properties":{"domain":{"type":"string"},"connected":{"type":"boolean","description":"A Cloudflare account is linked"},"connectUrl":{"type":"string","description":"The dashboard page that links Cloudflare"},"state":{"type":"string","enum":["none","preparing","prepared","switching","switched","unknown","cancelling","active","failed","cancelled"],"description":"preparing: the copy runs (stale: it stopped; prepare again resumes it). prepared: the copy is read back; switch next. switching: the nameserver change runs. unknown: we check whether the registrar took it. switched: waiting for Cloudflare. active: Cloudflare reports the zone active. failed: see reason. cancelled."},"moveId":{"type":["string","null"]},"zoneStatus":{"type":["string","null"],"enum":["pending","active",null]},"reusedZone":{"type":"boolean","description":"The zone was already in the Cloudflare account (pending)"},"nameservers":{"type":"array","items":{"type":"string"},"description":"The two Cloudflare assigned"},"diff":{"type":["object","null"],"description":"The last readback against the copy. The switch needs missing, different and extra empty.","properties":{"same":{"type":"integer"},"missing":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}}},"different":{"type":"array","items":{"type":"object","properties":{"want":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}},"got":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}}}}},"extra":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}}},"skipped":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"name":{"type":"string"}}}}}},"reason":{"type":["string","null"]},"stale":{"type":"boolean"},"done":{"type":"boolean","description":"Active at Cloudflare and visible in public DNS"},"preparedAt":{"type":["string","null"],"format":"date-time"},"switchedAt":{"type":["string","null"],"format":"date-time","description":"When the switch was asked for. Set while switching or unknown too: only state switched or active says the registrar took it"},"activeAt":{"type":["string","null"],"format":"date-time"},"publicDns":{"type":["object","null"],"description":"GET /api/domains/{name}/cloudflare, once the nameservers changed"}}}}}},"401":{"description":"No key or session","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"409":{"description":"Managed outside this service","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}},"delete":{"operationId":"cancel_cloudflare_move","description":"Cancels a prepared move. Deletes the zone only when this service created it and it is still pending. Refused once the switch started.","security":[{"bearer":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"responses":{"200":{"description":"The cancelled move","content":{"application/json":{"schema":{"type":"object","required":["domain","connected","connectUrl","state","moveId","zoneStatus","reusedZone","nameservers","diff","reason","stale","done"],"properties":{"domain":{"type":"string"},"connected":{"type":"boolean","description":"A Cloudflare account is linked"},"connectUrl":{"type":"string","description":"The dashboard page that links Cloudflare"},"state":{"type":"string","enum":["none","preparing","prepared","switching","switched","unknown","cancelling","active","failed","cancelled"],"description":"preparing: the copy runs (stale: it stopped; prepare again resumes it). prepared: the copy is read back; switch next. switching: the nameserver change runs. unknown: we check whether the registrar took it. switched: waiting for Cloudflare. active: Cloudflare reports the zone active. failed: see reason. cancelled."},"moveId":{"type":["string","null"]},"zoneStatus":{"type":["string","null"],"enum":["pending","active",null]},"reusedZone":{"type":"boolean","description":"The zone was already in the Cloudflare account (pending)"},"nameservers":{"type":"array","items":{"type":"string"},"description":"The two Cloudflare assigned"},"diff":{"type":["object","null"],"description":"The last readback against the copy. The switch needs missing, different and extra empty.","properties":{"same":{"type":"integer"},"missing":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}}},"different":{"type":"array","items":{"type":"object","properties":{"want":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}},"got":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}}}}},"extra":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"},"value":{"type":"string"},"ttl":{"type":"integer"},"prio":{"type":"integer"}}}},"skipped":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"name":{"type":"string"}}}}}},"reason":{"type":["string","null"]},"stale":{"type":"boolean"},"done":{"type":"boolean","description":"Active at Cloudflare and visible in public DNS"},"preparedAt":{"type":["string","null"],"format":"date-time"},"switchedAt":{"type":["string","null"],"format":"date-time","description":"When the switch was asked for. Set while switching or unknown too: only state switched or active says the registrar took it"},"activeAt":{"type":["string","null"],"format":"date-time"},"publicDns":{"type":["object","null"],"description":"GET /api/domains/{name}/cloudflare, once the nameservers changed"}}}}}},"401":{"description":"Missing or revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"409":{"description":"No open move, or the switch started","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/domains/{name}/zone-file":{"get":{"operationId":"export_zone_file","description":"The zone as a BIND file, to import in Cloudflare (DNS → Records → Import and Export), as an attachment. Records the file cannot hold safely are listed as ; skipped comments. Errors are JSON.","security":[{"bearer":[]},{"session":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"responses":{"200":{"description":"The zone file","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"No key or session","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"409":{"description":"Managed outside this service","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"502":{"description":"Our registrar did not answer","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/domains/{name}/dnssec":{"put":{"operationId":"turn_off_dnssec","description":"Asks to turn DNSSEC off before a move to Cloudflare. Only { enabled: false } is accepted. It waits for the account owner: the answer is 202, we email them a link that works once, for 30 minutes, and nothing changes until they confirm it on /account/confirm, signed in to the same account. The same request while its link is open answers alreadySent: true and sends no new email. Revoking the key cancels its open requests. The 202 answer's action is dnssec_off. Once confirmed, the registrar's setting goes off at once and the registry removes the DS record from public DNS within about a day (GET /api/domains/{name}/cloudflare: dnssec.publicDs).","security":[{"bearer":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["enabled"],"properties":{"enabled":{"type":"boolean","enum":[false]}}}}}},"responses":{"202":{"description":"Waits for the owner: we emailed the account owner a single-use link. Nothing changes until they confirm it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmationSent"}}}},"400":{"description":"Anything but enabled: false","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"401":{"description":"Missing or revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"409":{"description":"Managed outside this service","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"429":{"description":"5 confirmation requests for this account in the last hour; nothing changed","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"503":{"description":"We could not email the account owner; nothing changed","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/account/domains/{name}/nameservers-check":{"post":{"operationId":"check_nameservers","description":"The dashboard's check before a nameserver change: the same rule as PUT /api/domains/{name}/nameservers, and the hosts public DNS does not find. It changes nothing, logs nothing and emails nobody.","security":[{"session":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["nameservers"],"properties":{"nameservers":{"type":"array","maxItems":26,"items":{"type":"string","maxLength":253}}}}}}},"responses":{"200":{"description":"The list as it would be saved, and the warnings","content":{"application/json":{"schema":{"type":"object","properties":{"nameservers":{"type":"array","items":{"type":"string"},"description":"Cleaned: lower case, no trailing dot, each once. Empty: back to our nameservers."},"warnings":{"type":"array","items":{"type":"string"},"description":"The hosts public DNS does not find, one sentence each. Advisory: they never block the change."}}}}}},"400":{"description":"The list the save would refuse, with the same sentence","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"401":{"description":"Not signed in","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"409":{"description":"Managed outside this service","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/domains/{name}/lock":{"put":{"operationId":"set_transfer_lock","description":"locked: true locks the domain at once and answers 200. locked: false asks to unlock it, which a transfer away needs. It waits for the account owner: the answer is 202, we email them a link that works once, for 30 minutes, and nothing changes until they confirm it on /account/confirm, signed in to the same account. The same request while its link is open answers alreadySent: true and sends no new email. Revoking the key cancels its open requests.","security":[{"bearer":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["locked"],"properties":{"locked":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Locked now (locked: true)","content":{"application/json":{"schema":{"type":"object","properties":{"locked":{"type":"boolean","enum":[true]}}}}}},"202":{"description":"Waits for the owner: we emailed the account owner a single-use link. Nothing changes until they confirm it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmationSent"}}}},"400":{"description":"The extension cannot be locked at its registry","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"401":{"description":"Missing or revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"429":{"description":"5 confirmation requests for this account in the last hour; nothing changed","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"502":{"description":"Our registrar did not answer; nothing changed","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"503":{"description":"We could not email the account owner; nothing changed","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/domains/{name}/auto-renew":{"put":{"operationId":"set_auto_renew","description":"enabled: false turns auto-renew off at once and answers 200; off always works. enabled: true asks to turn it on. On: we charge the saved card 7 days before expiry, then renew for one year once the payment is in. It waits for the account owner: the answer is 202, we email them a link that works once, for 30 minutes, and nothing changes until they confirm it on /account/confirm, signed in to the same account. The same request while its link is open answers alreadySent: true and sends no new email. Revoking the key cancels its open requests. A domain already on answers 200 { autoRenew: true } at once. Turning it on needs a card the owner saved with Stripe through Manage payment method in the dashboard (save_card_url; autoRenewAvailable on GET /api/domains/{name}); without one, the 409 answer adds save_card_url, the dashboard page linking to Stripe to manage payment methods. Only our switch changes: nothing is sent to the registrar.","security":[{"bearer":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["enabled"],"properties":{"enabled":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Auto-renew now: off (enabled: false), or on already","content":{"application/json":{"schema":{"type":"object","properties":{"autoRenew":{"type":"boolean"}}}}}},"202":{"description":"Waits for the owner: we emailed the account owner a single-use link. Nothing changes until they confirm it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmationSent"}}}},"400":{"description":"Bad body","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"401":{"description":"Missing or revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"409":{"description":"Auto-renew cannot be turned on: no saved card, an expired domain, a registrant whose country cannot hold the .fr or .eu name (renewBlocked on GET /api/domains/{name}), or not available on this deployment","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"429":{"description":"5 confirmation requests for this account in the last hour; nothing changed","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"503":{"description":"We could not email the account owner; nothing changed","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/domains/{name}/auth-code":{"post":{"operationId":"get_auth_code","description":"Asks for the transfer code. A POST so it is never cached or prefetched. It waits for the account owner: the answer is 202, we email them a link that works once, for 30 minutes, and nothing changes until they confirm it on /account/confirm, signed in to the same account. The same request while its link is open answers alreadySent: true and sends no new email. Revoking the key cancels its open requests. The code never comes back here: the owner sees it on the confirmation page. Some registries (.eu, .be) email the code to the registrant instead.","security":[{"bearer":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"}],"responses":{"202":{"description":"Waits for the owner: we emailed the account owner a single-use link. Nothing changes until they confirm it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmationSent"}}}},"401":{"description":"Missing or revoked API key","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"429":{"description":"5 confirmation requests for this account in the last hour; nothing changed","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"503":{"description":"We could not email the account owner; nothing changed","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}},"/api/domains/{name}/activity":{"get":{"operationId":"get_domain_activity","security":[{"bearer":[]},{"session":[]}],"parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"},"description":"A domain of the account, for example ada.fr"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"Newest first","content":{"application/json":{"schema":{"type":"object","properties":{"events":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"domain":{"type":"string"},"actor":{"type":"string","description":"web (the dashboard), key:<label> (an API key), oauth:<app name> or oauth (a connected app), system (a renewal)"},"actorId":{"type":["string","null"],"description":"The key's id or the app's OAuth client id; null for web, system and events logged before this field"},"action":{"type":"string","description":"dns.add, dns.update, dns.remove, nameservers.set, lock.set, autorenew.on, autorenew.off, authcode.read, renew.charged, renew.declined (the saved card was refused; detail: { orderId, step, reason }), renew.no_card (no card to charge; detail: { step }, or { orderId, step } when the payment provider found none), renew.refunded (a paid renewal did not go through and was refunded; detail: { orderId, refundCents }), renew.ineligible (not renewed automatically: the registrant's country cannot hold the .fr or .eu name, so nothing was charged; detail: { step }), renew.done, confirm.requested (an agent asked for a change that waits for the owner; detail: { action, confirmation }), confirm.refused (the owner refused it; detail: { action, confirmation }), cloudflare.requested (a move to Cloudflare was asked; detail: { nameservers }), cloudflare.live (public DNS shows the Cloudflare nameservers; detail: { nameservers }), cloudflare.failed (the move failed; detail: { reason, stage? }), cloudflare.replaced (a manual nameserver change replaced an open move), dnssec.off (DNSSEC turned off), cloudflare.prepared (the records were copied to the linked Cloudflare account; detail: { zone, copied, same, skipped, extra, reused }), cloudflare.prepare_failed (detail: { stage, code, reason }), cloudflare.active (Cloudflare reports the zone active), cloudflare.drift (Cloudflare's records differ from the copy after activation; detail: { zone, missing, different, extra }), cloudflare.cancelled (detail: { zone, zoneDeleted })"},"detail":{"type":["object","null"]},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"400":{"description":"Bad limit","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"401":{"description":"No key or session","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}},"404":{"description":"Not a domain of this account","content":{"application/json":{"schema":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"What went wrong, in plain words"}}}}}}}}}}}