Skip to content
Coritan Docs

Client API: Domains

Domain search, registration, renewals, nameservers, and locks.

View as Markdown

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.

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 costs

GET /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.

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 /api/v1/domains/pricing

Get available TLD pricing.

Authentication: an access token, sent as Authorization: Bearer <token>.

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

POST /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>.

application/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
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 registrations

GET /api/v1/domains/registrations

List user's domain registrations.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required Description
page query integer no Default: 1.
per_page query integer no Default: 25.
status query string no
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 registration

GET /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>.

Name In Type Required
reg_id path integer yes
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 out

GET /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>.

Name In Type Required
reg_id path integer yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

PUT /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>.

Name In Type Required
reg_id path integer yes

application/json (required)

Field Type Required
enabled boolean yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

PUT /api/v1/domains/registrations/{reg_id}/lock

Lock or unlock a domain.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
reg_id path integer yes

application/json (required)

Field Type Required
enabled boolean yes
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 domain

PUT /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>.

Name In Type Required
reg_id path integer yes

application/json (required)

Field Type Required
nameservers array of string yes
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 status

GET /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>.

Name In Type Required
reg_id path integer yes
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 registry

PUT /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>.

Name In Type Required
reg_id path integer yes

application/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
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 credit

POST /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>.

Name In Type Required
reg_id path integer yes

application/json (required)

Field Type Required
duration integer no
Status Meaning
202 Success.
422 The request is not valid. detail lists each problem.

GET /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>.

Name In Type Required
reg_id path integer yes
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 domain

PUT /api/v1/domains/registrations/{reg_id}/whois-privacy

Toggle WHOIS privacy for a domain.

Authentication: an access token, sent as Authorization: Bearer <token>.

Name In Type Required
reg_id path integer yes

application/json (required)

Field Type Required
enabled boolean yes
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 costs

POST /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>.

application/json (required)

Field Type Required
domain string yes
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 credit

POST /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>.

application/json (required)

Field Type Required
domain string yes
auth_code string yes
Status Meaning
202 Success.
422 The request is not valid. detail lists each problem.

POST /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>.

application/json (required)

Field Type Required
domain string yes
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