Client API: Domains
Domain search, registration, renewals, nameservers, and locks.
Domain search, registration, renewals, nameservers, and locks.
Base URL: https://api.coritan.com/api/v1. Paths below are complete.
To try these requests in the browser, open the interactive Client API reference.
Operations
Section titled Operations| Method | Path | Summary |
|---|---|---|
| GET | /api/v1/domains/prices |
What a year of each domain extension costs |
| GET | /api/v1/domains/pricing |
Get available TLD pricing |
| POST | /api/v1/domains/register |
Register a new domain name |
| GET | /api/v1/domains/registrations |
List user's domain registrations |
| GET | /api/v1/domains/registrations/{reg_id} |
Get details of a specific domain registration |
| GET | /api/v1/domains/registrations/{reg_id}/auth-code |
Get the EPP/auth code for domain transfer out |
| PUT | /api/v1/domains/registrations/{reg_id}/auto-renew |
Turn auto-renew on or off |
| PUT | /api/v1/domains/registrations/{reg_id}/lock |
Lock or unlock a domain |
| PUT | /api/v1/domains/registrations/{reg_id}/nameservers |
Update nameservers for a domain |
| GET | /api/v1/domains/registrations/{reg_id}/registrant |
The domain's registrant contact as we hold it, whatever the registration's status |
| PUT | /api/v1/domains/registrations/{reg_id}/registrant |
Replace the domain's registrant contact and send it to the registry |
| POST | /api/v1/domains/registrations/{reg_id}/renew |
Renew a registration at the registry for duration years, paid from credit |
| GET | /api/v1/domains/registrations/{reg_id}/renewal |
Renewal quote |
| PUT | /api/v1/domains/registrations/{reg_id}/whois-privacy |
Toggle WHOIS privacy for a domain |
| POST | /api/v1/domains/search |
Check whether a domain name is free to register and what a year costs |
| POST | /api/v1/domains/transfer |
Start moving a domain from another registrar to us, paid from credit |
| POST | /api/v1/domains/transfer/quote |
Transfer quote |
What a year of each domain extension costs
Section titled What a year of each domain extension costsGET /api/v1/domains/prices
What a year of each domain extension costs. No sign in needed.
Every extension we sell, sorted by name, with the price of one year of
registration, renewal and a transfer in, as strings with two decimals in
currency. These are the prices we charge: a renewal and a transfer
charge exactly the listed renew and transfer, and a registration
charges the registrar's price for the name with the same markup, which
for an ordinary name is the listed register (the price of a premium
name can be higher, and POST /api/v1/domains/search shows it before you
pay). min_years and max_years are how many years one purchase may
cover, and on_sale marks a limited registration offer. The list is
refreshed from the registrar once a day, and updated_at says when.
Until the first refresh has run, the list holds the common extensions
(.com, .net, .org and about thirty more), priced from the registrar's
price list the same way, and updated_at is null. Shared caches may keep
the answer for a minute.
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
Fields of a 200 response:
| Field | Type | Description |
|---|---|---|
currency |
string | The currency of every price, such as USD |
tlds |
array of DomainPriceOut | |
tlds[].tld |
string | The extension with its dot, such as .com |
tlds[].register |
string | The price of one year of registration, with two decimals |
tlds[].renew |
string | The price of one year of renewal |
tlds[].transfer |
string | The price of a transfer in, which adds a year |
tlds[].restore |
string or null | The price of restoring an expired name. Null when the registrar names none. |
tlds[].min_years |
integer | The fewest years one purchase may cover |
tlds[].max_years |
integer | The most years one purchase may cover |
tlds[].on_sale |
boolean | Whether the registration price is a limited offer |
updated_at |
string (date-time) or null | When the list was last refreshed from the registrar. Null if it never was. |
Get available TLD pricing
Section titled Get available TLD pricingGET /api/v1/domains/pricing
Get available TLD pricing.
Authentication: an access token, sent as Authorization: Bearer <token>.
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
A 200 response is a list; each item has these fields:
| Field | Type |
|---|---|
[].tld |
string |
[].register_price |
string |
[].renew_price |
string |
[].transfer_price |
string or null |
[].currency |
string |
Register a new domain name
Section titled Register a new domain namePOST /api/v1/domains/register
Register a new domain name. Charges user credit balance first, then provisions.
The charge is the price per year that POST /search shows, times
duration. When the account's credit does not cover it, the answer is
402 before anything is charged, with detail set to {"error": "insufficient_credit", "message", "required", "available", "currency"};
the two amounts are strings with two decimals. A renewal and a transfer
answer the same 402 when the credit does not cover them.
The charge and its ledger row are committed before we ask the registrar.
When the registrar refuses, or does not answer, we give the charge back
with a second ledger row and answer 502. When we cannot reach a registrar
at all (503 with the detail "Domain registration is not available right
now." and no Retry-After), nothing is charged, or the charge is given
back the same way.
A domain on our nameservers (the default when nameservers is empty)
gets a DNS zone, and so does one with auto_proxy or auto_ssl: the
customer's own zone of that name, or a new one. A zone another account
holds is never linked. The registration still stands, the response sets
dns_zone_conflict with a dns_zone_message for the customer, and a
dns_zone_conflict domain event names the zone. A proxy route another
account holds is treated the same way (proxy_route_conflict, and no
SSL order for it). A zone counts as a website, so when the account's plan
has no room for one more the answer is 402, before anything is charged.
auto_proxy creates a proxy route for the domain, and auto_ssl a
certificate for it, only when proxy_origin ({host, port, ssl})
names where the site runs. host must be a public address: a private,
loopback or reserved address, or a name that resolves to one, answers 422
with field proxy_origin before anything is charged. Without
proxy_origin no route is created: the answer sets
proxy_route_skipped with a proxy_route_message, orders no
certificate, and you add the route later under Domain Management, Edge Proxy.
proxy_origin does nothing while auto_proxy is false.
registrant is optional and takes the fields of
PUT /registrations/{reg_id}/registrant, checked the same way (422 with
one entry per field under registrant). It is created at the registry
before any credit is taken, a refusal answers 502, and the domain is
registered with it as the registrant. Without it, the registrar's default
contact is the registrant.
Authentication: an access token, sent as Authorization: Bearer <token>.
Request body
Section titled Request bodyapplication/json (required)
| Field | Type | Required | Description |
|---|---|---|---|
domain |
string | yes | |
duration |
integer | no | |
nameservers |
array of string or null | no | |
auto_ssl |
boolean | no | |
auto_proxy |
boolean | no | |
whois_privacy |
boolean | no | |
registrant |
RegistrantBody or null | no | |
registrant.name |
string or null | no | |
registrant.organization |
string or null | no | |
registrant.email |
string or null | no | |
registrant.phone |
string or null | no | |
registrant.address_line1 |
string or null | no | |
registrant.address_line2 |
string or null | no | |
registrant.city |
string or null | no | |
registrant.region |
string or null | no | |
registrant.postcode |
string or null | no | |
registrant.country |
string or null | no | |
registrant.country_name |
string or null | no | |
proxy_origin |
ProxyOriginBody or null | no | |
proxy_origin.host |
string | yes | A public hostname or address, never a private or loopback one |
proxy_origin.port |
integer or null | no | 80, or 443 with ssl |
proxy_origin.ssl |
boolean | no | Whether the origin takes HTTPS |
Responses
Section titled Responses| Status | Meaning |
|---|---|
201 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Fields of a 201 response:
| Field | Type |
|---|---|
id |
integer |
domain |
string |
status |
string |
registered_at |
string (date-time) or null |
expires_at |
string (date-time) or null |
nameservers |
array of string or null |
whois_privacy |
boolean |
locked |
boolean |
auto_renew |
boolean |
auto_ssl |
boolean |
auto_proxy |
boolean |
dns_zone_id |
integer or null |
dns_zone_conflict |
boolean |
dns_zone_message |
string or null |
proxy_route_id |
integer or null |
proxy_route_conflict |
boolean |
proxy_route_skipped |
boolean |
proxy_route_message |
string or null |
ssl_certificate_id |
integer or null |
List user's domain registrations
Section titled List user's domain registrationsGET /api/v1/domains/registrations
List user's domain registrations.
Authentication: an access token, sent as Authorization: Bearer <token>.
Parameters
Section titled Parameters| Name | In | Type | Required | Description |
|---|---|---|---|---|
page |
query | integer | no | Default: 1. |
per_page |
query | integer | no | Default: 25. |
status |
query | string | no |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Fields of a 200 response:
| Field | Type |
|---|---|
registrations |
array of DomainRegistrationResponse |
registrations[].id |
integer |
registrations[].domain |
string |
registrations[].status |
string |
registrations[].registered_at |
string (date-time) or null |
registrations[].expires_at |
string (date-time) or null |
registrations[].nameservers |
array of string or null |
registrations[].whois_privacy |
boolean |
registrations[].locked |
boolean |
registrations[].auto_renew |
boolean |
registrations[].auto_ssl |
boolean |
registrations[].auto_proxy |
boolean |
registrations[].dns_zone_id |
integer or null |
registrations[].dns_zone_conflict |
boolean |
registrations[].dns_zone_message |
string or null |
registrations[].proxy_route_id |
integer or null |
registrations[].proxy_route_conflict |
boolean |
registrations[].proxy_route_skipped |
boolean |
registrations[].proxy_route_message |
string or null |
registrations[].ssl_certificate_id |
integer or null |
total |
integer |
Get details of a specific domain registration
Section titled Get details of a specific domain registrationGET /api/v1/domains/registrations/{reg_id}
Get details of a specific domain registration.
service_id is the service the domain was ordered with, or null.
renews_with_service is true when that service's invoices pay for the
renewals (it bills a year or more at a time), so the domain renews once
its invoice is paid and POST /registrations/{reg_id}/renew answers
409; otherwise renewals are paid from credit.
Authentication: an access token, sent as Authorization: Bearer <token>.
Parameters
Section titled Parameters| Name | In | Type | Required |
|---|---|---|---|
reg_id |
path | integer | yes |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Fields of a 200 response:
| Field | Type |
|---|---|
id |
integer |
domain |
string |
status |
string |
registered_at |
string (date-time) or null |
expires_at |
string (date-time) or null |
nameservers |
array of string or null |
whois_privacy |
boolean |
locked |
boolean |
auto_renew |
boolean |
auto_ssl |
boolean |
auto_proxy |
boolean |
dns_zone_id |
integer or null |
dns_zone_conflict |
boolean |
dns_zone_message |
string or null |
proxy_route_id |
integer or null |
proxy_route_conflict |
boolean |
proxy_route_skipped |
boolean |
proxy_route_message |
string or null |
ssl_certificate_id |
integer or null |
service_id |
integer or null |
renews_with_service |
boolean |
Get the EPP/auth code for domain transfer out
Section titled Get the EPP/auth code for domain transfer outGET /api/v1/domains/registrations/{reg_id}/auth-code
Get the EPP/auth code for domain transfer out.
Authentication: an access token, sent as Authorization: Bearer <token>.
Parameters
Section titled Parameters| Name | In | Type | Required |
|---|---|---|---|
reg_id |
path | integer | yes |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Turn auto-renew on or off
Section titled Turn auto-renew on or offPUT /api/v1/domains/registrations/{reg_id}/auto-renew
Turn auto-renew on or off.
While it is on, the daily auto-renew job renews the domain for a year in
its last domains.renewal_window_days days and takes the price from
the account's credit first. Either way we ask the registrar never to
renew the domain by itself, since the customer would not pay for such a
renewal; its answer changes nothing here. A domain whose service pays for
its renewals renews with the service, whatever this says. A registration
that is not the caller's, or not active or expiring_soon, answers
404.
Authentication: an access token, sent as Authorization: Bearer <token>.
Parameters
Section titled Parameters| Name | In | Type | Required |
|---|---|---|---|
reg_id |
path | integer | yes |
Request body
Section titled Request bodyapplication/json (required)
| Field | Type | Required |
|---|---|---|
enabled |
boolean | yes |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Lock or unlock a domain
Section titled Lock or unlock a domainPUT /api/v1/domains/registrations/{reg_id}/lock
Lock or unlock a domain.
Authentication: an access token, sent as Authorization: Bearer <token>.
Parameters
Section titled Parameters| Name | In | Type | Required |
|---|---|---|---|
reg_id |
path | integer | yes |
Request body
Section titled Request bodyapplication/json (required)
| Field | Type | Required |
|---|---|---|
enabled |
boolean | yes |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Update nameservers for a domain
Section titled Update nameservers for a domainPUT /api/v1/domains/registrations/{reg_id}/nameservers
Update nameservers for a domain.
Moving a domain onto our nameservers links a DNS zone by the same rule as
registration: the customer's own zone, or a new one, never another
account's (dns_zone_conflict and dns_zone_message then say so).
A new zone counts as a website, so when the account's plan has no room
for one more the answer is 402 and the nameservers stay as they were.
Authentication: an access token, sent as Authorization: Bearer <token>.
Parameters
Section titled Parameters| Name | In | Type | Required |
|---|---|---|---|
reg_id |
path | integer | yes |
Request body
Section titled Request bodyapplication/json (required)
| Field | Type | Required |
|---|---|---|
nameservers |
array of string | yes |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
The domain's registrant contact as we hold it, whatever the registration's status
Section titled The domain's registrant contact as we hold it, whatever the registration's statusGET /api/v1/domains/registrations/{reg_id}/registrant
The domain's registrant contact as we hold it, whatever the
registration's status. registrant is null until someone saves one or
an order stored one. registry.status is sent once the registry
holds this contact as the domain's registrant, with sent_at, and
not_sent while it does not. A registration that is not the caller's
answers 404. Team members read the contact of a domain on the account they
act for.
Platform accounts only: a brand's customer portal has no domain routes.
Authentication: an access token, sent as Authorization: Bearer <token>.
Parameters
Section titled Parameters| Name | In | Type | Required |
|---|---|---|---|
reg_id |
path | integer | yes |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Fields of a 200 response:
| Field | Type |
|---|---|
domain |
string |
registrant |
RegistrantContact or null |
registrant.name |
string or null |
registrant.organization |
string or null |
registrant.email |
string or null |
registrant.phone |
string or null |
registrant.address_line1 |
string or null |
registrant.address_line2 |
string or null |
registrant.city |
string or null |
registrant.region |
string or null |
registrant.postcode |
string or null |
registrant.country |
string or null |
registrant.country_name |
string or null |
registry |
RegistrantRegistry |
registry.status |
string, one of sent, not_sent |
registry.sent_at |
string (date-time) or null |
Replace the domain's registrant contact and send it to the registry
Section titled Replace the domain's registrant contact and send it to the registryPUT /api/v1/domains/registrations/{reg_id}/registrant
Replace the domain's registrant contact and send it to the registry.
name, email, phone, address_line1, city and country
(ISO 3166-1 alpha-2) are required, and organization,
address_line2, region and postcode are not; a field left out
is cleared. phone is + and the country code, a space, dot or
hyphen, then the number, and is stored as +CC.NUMBER. The fields the
GET adds may be sent back and are ignored; any other field is a 422. A
wrong value answers 422 with one entry per field, and more than
REGISTRANT_SAVES saves in an hour across the account answer 429. A
registration that is not the caller's, or not active, answers 404.
We create a new contact at the registrar and make it the domain's registrant; the admin, technical and billing contacts stay as they are. When the registry refuses the contact or does not answer, the answer is 502 with the reason and nothing we hold changes. Saving the contact the registry already holds asks it nothing. Each change is written to the audit log with the fields that changed. Team members with the Technical or Admin role save the contact of a domain on the account they act for.
Platform accounts only: a brand's customer portal has no domain routes.
Authentication: an access token, sent as Authorization: Bearer <token>.
Parameters
Section titled Parameters| Name | In | Type | Required |
|---|---|---|---|
reg_id |
path | integer | yes |
Request body
Section titled Request bodyapplication/json (required)
| Field | Type | Required |
|---|---|---|
name |
string or null | no |
organization |
string or null | no |
email |
string or null | no |
phone |
string or null | no |
address_line1 |
string or null | no |
address_line2 |
string or null | no |
city |
string or null | no |
region |
string or null | no |
postcode |
string or null | no |
country |
string or null | no |
country_name |
string or null | no |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Fields of a 200 response:
| Field | Type |
|---|---|
domain |
string |
registrant |
RegistrantContact or null |
registrant.name |
string or null |
registrant.organization |
string or null |
registrant.email |
string or null |
registrant.phone |
string or null |
registrant.address_line1 |
string or null |
registrant.address_line2 |
string or null |
registrant.city |
string or null |
registrant.region |
string or null |
registrant.postcode |
string or null |
registrant.country |
string or null |
registrant.country_name |
string or null |
registry |
RegistrantRegistry |
registry.status |
string, one of sent, not_sent |
registry.sent_at |
string (date-time) or null |
Renew a registration at the registry for duration years, paid from credit
Section titled Renew a registration at the registry for duration years, paid from creditPOST /api/v1/domains/registrations/{reg_id}/renew
Renew a registration at the registry for duration years, paid from credit.
The charge is the price for a year from GET /registrations/{reg_id}/renewal
times duration. We take it from the account's credit with a ledger
row and commit before we ask the registry. When the registry refuses, or
does not answer, we give the charge back with a second ledger row and
answer 502, or 503 with the detail "Domain registration is not available
right now." when we cannot reach a registrar at all. A balance that does
not cover the charge answers 402 before anything is taken, with the detail that POST /register sends
(error is insufficient_credit). A domain whose service pays for
its renewals renews once the service's invoice is paid, so it answers
409 with detail.error set to renews_with_service and the
service_id, and nothing is charged. The charge, the renewal and a
refund each write an audit log entry.
A registration renews while it is active or expiring_soon: the
second is its last 30 days, when the expiry emails ask the customer to
renew. Any other status, or another account's registration, answers 404.
The registration then ends on the date the registry reported or, when it
reported none, on its old end date plus the years renewed, as auto-renew
does. new_expiry in the answer is the registry's date or null,
charged the amount taken (a string with two decimals) and
currency its currency.
Authentication: an access token, sent as Authorization: Bearer <token>.
Parameters
Section titled Parameters| Name | In | Type | Required |
|---|---|---|---|
reg_id |
path | integer | yes |
Request body
Section titled Request bodyapplication/json (required)
| Field | Type | Required |
|---|---|---|
duration |
integer | no |
Responses
Section titled Responses| Status | Meaning |
|---|---|
202 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Renewal quote
Section titled Renewal quoteGET /api/v1/domains/registrations/{reg_id}/renewal
The price of a year of renewal, which POST /registrations/{reg_id}/renew
charges times its duration: the TLD's renew_price from
GET /pricing when it lists one, and otherwise the registrar's price
with our markup, as POST /search shows it. It answers 404 and 409 as
the renewal does, 502 when there is no price, and 503 with the detail
"Domain registration is not available right now." when we cannot reach a
registrar to price it.
Authentication: an access token, sent as Authorization: Bearer <token>.
Parameters
Section titled Parameters| Name | In | Type | Required |
|---|---|---|---|
reg_id |
path | integer | yes |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Fields of a 200 response:
| Field | Type |
|---|---|
domain |
string |
renew_price |
string |
currency |
string |
Toggle WHOIS privacy for a domain
Section titled Toggle WHOIS privacy for a domainPUT /api/v1/domains/registrations/{reg_id}/whois-privacy
Toggle WHOIS privacy for a domain.
Authentication: an access token, sent as Authorization: Bearer <token>.
Parameters
Section titled Parameters| Name | In | Type | Required |
|---|---|---|---|
reg_id |
path | integer | yes |
Request body
Section titled Request bodyapplication/json (required)
| Field | Type | Required |
|---|---|---|
enabled |
boolean | yes |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Check whether a domain name is free to register and what a year costs
Section titled Check whether a domain name is free to register and what a year costsPOST /api/v1/domains/search
Check whether a domain name is free to register and what a year costs.
price is the price for one year with our markup, in currency.
Answers 503 with Retry-After when the registrar is busy or does not
answer: repeat the search. Answers 503 without Retry-After and the
detail "Domain registration is not available right now." when we cannot
reach a registrar at all: repeating does not help. Answers 502 when the
registrar refuses the request. The registrar's own wording is never sent.
Authentication: an access token, sent as Authorization: Bearer <token>.
Request body
Section titled Request bodyapplication/json (required)
| Field | Type | Required |
|---|---|---|
domain |
string | yes |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Fields of a 200 response:
| Field | Type |
|---|---|
domain |
string |
available |
boolean |
price |
string or null |
currency |
string |
premium |
boolean |
Start moving a domain from another registrar to us, paid from credit
Section titled Start moving a domain from another registrar to us, paid from creditPOST /api/v1/domains/transfer
Start moving a domain from another registrar to us, paid from credit.
A transfer adds a year to the registration and costs the price from
POST /transfer/quote. We take it from the account's credit with a
ledger row and commit before we ask the registrar. When the registrar
refuses the transfer, or does not answer, we give the charge back with a
second ledger row and answer 502. When we cannot reach a registrar at all
the answer is 503 with the detail "Domain registration is not available
right now.", after the same refund. A balance that does not cover the
charge answers 402 before anything is taken, with the detail that
POST /register sends. A domain we already hold answers 409. The
charge, the start and a refund each write an audit log entry.
The registration is pending_transfer until the transfer completes.
charged in the answer is the amount taken and currency its currency.
Authentication: an access token, sent as Authorization: Bearer <token>.
Request body
Section titled Request bodyapplication/json (required)
| Field | Type | Required |
|---|---|---|
domain |
string | yes |
auth_code |
string | yes |
Responses
Section titled Responses| Status | Meaning |
|---|---|
202 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Transfer quote
Section titled Transfer quotePOST /api/v1/domains/transfer/quote
What POST /transfer charges for domain: the TLD's
transfer_price from GET /pricing when it lists one, and otherwise
the registrar's price with our markup. 502 when there is no price, and
503 with the detail "Domain registration is not available right now."
when we cannot reach a registrar to price it.
Authentication: an access token, sent as Authorization: Bearer <token>.
Request body
Section titled Request bodyapplication/json (required)
| Field | Type | Required |
|---|---|---|
domain |
string | yes |
Responses
Section titled Responses| Status | Meaning |
|---|---|
200 |
Success. |
422 |
The request is not valid. detail lists each problem. |
Fields of a 200 response:
| Field | Type |
|---|---|
domain |
string |
transfer_price |
string |
currency |
string |