runlot
ReferenceAPI

Domain purchase and renewal

Covers the 10 API operations in the domains category.

MethodPathDescription
GET/v1/orgs/{orgSlug}/domainsThe organization's domains (runlot domains list)
POST/v1/orgs/{orgSlug}/domainsBuy a domain (runlot domains buy)
POST/v1/orgs/{orgSlug}/domains/checkLook up a domain name (runlot domains check)
POST/v1/orgs/{orgSlug}/domains/importImport a domain you already own (runlot domains import)
GET/v1/orgs/{orgSlug}/domains/{name}Domain details and recent change history (runlot domains show)
POST/v1/orgs/{orgSlug}/domains/{name}/renewRenew (runlot domains renew)
POST/v1/orgs/{orgSlug}/domains/{name}/auto-renewChange the auto-renew intent
POST/v1/orgs/{orgSlug}/domains/{name}/lockTurn the transfer lock on and off (runlot domains lock|unlock)
POST/v1/orgs/{orgSlug}/domains/{name}/auth-codeCheck the transfer auth code (runlot domains auth-code)
POST/v1/orgs/{orgSlug}/domains/{name}/syncRe-read from the registrar now

GET /v1/orgs/{orgSlug}/domains

Requires viewer or above.

operationId listDomains

StatusDescriptionResponse body
200ListDomainList
403
404
503no_core — a cp-public started without cp-coreError

POST /v1/orgs/{orgSlug}/domains

Requires admin or above — it spends money. Audit event domain.purchase (contacts are not recorded: the audit log cannot be erased and contact details are personal data).

Right after registration the NS records point at the runlot nameservers (ns1~3.runlot.app). No ownership-verification step is needed, so the domain can be connected to an app immediately after purchase. The ICANN verification email goes to the address in contact: the UI must say so before registration (§5.5).

Sending the same request again is safe. A completed domain returns 200, and a purchase that was interrupted midway resumes from the step where it stopped.

operationId purchaseDomain

Request body: application/json · object

StatusDescriptionResponse body
200Domain already purchased (idempotent)Domain
201Purchase completeDomain
400
402payment_failed — the payment was declinedError
403
409domain_taken·domain_unavailableError
422registrar_rejected — the registrar rejected a value in the request (contact details, for example). The registration never happened and retrying does not make it better. A request with corrected input has to be a new row.Error
502saga_incomplete·registrar_error — sending it again resumes where it stopped. The edge (Cloudflare) replaces the body of a 502 with its own HTML — a browser client never receives code. The server does not send failures that retrying cannot make better here.Error
503no_core·registrar_not_configured·dns_not_configuredError

POST /v1/orgs/{orgSlug}/domains/check

Requires member or above. Not viewer, because this single call burns a registrar API request — it looks like a read, but it goes outside.

priceCents is one year of initial registration, renewalCents is one year of renewal. They are separate because first-year discounts are common.

operationId checkDomains

Request body: application/json · object

StatusDescriptionResponse body
200Availability by nameobject
400
403
503no_core·registrar_not_configuredError

POST /v1/orgs/{orgSlug}/domains/import

Requires admin or above. Audit domain.import. It does not call the registrar — it creates one zone, and once the customer switches the NS records at their own registrar to ns1~3.runlot.app, full DNS management moves to us (§5.6).

operationId importDomain

Request body: application/json · object

StatusDescriptionResponse body
200Domain already imported (idempotent)Domain
201Import completeDomain
400
403
409domain_takenError
503no_core·dns_not_configuredError

GET /v1/orgs/{orgSlug}/domains/{name}

Requires viewer or above. A name that belongs to another organization is a 404.

operationId getDomain

StatusDescriptionResponse body
200DomainsDomainDetail
403
404

POST /v1/orgs/{orgSlug}/domains/{name}/renew

Requires admin or above. Audit domain.renew.

operationId renewDomain

Request body: application/json · object

StatusDescriptionResponse body
200Renewed domainDomain
400
403
404

POST /v1/orgs/{orgSlug}/domains/{name}/auto-renew

Requires admin or above. Auto-renew at the registrar stays on (§5.4) — a domain is an asset you lose if you are one day late, so we renew first and bill afterwards. The UI must say this too: otherwise a customer turns it off here and believes they have cancelled.

operationId setDomainAutoRenew

Request body: application/json · object

StatusDescriptionResponse body
200Updated domainDomain
400
403
404

POST /v1/orgs/{orgSlug}/domains/{name}/lock

Requires admin or above. Audit domain.lock.

operationId setDomainLock

Request body: application/json · object

StatusDescriptionResponse body
200Updated domainDomain
400
403
404

POST /v1/orgs/{orgSlug}/domains/{name}/auth-code

Requires admin or above. Audit domain.auth_codethe code itself is not written to the audit log: anyone holding the code can take the domain, and audit records cannot be deleted.

The way out is open at any time (§5.5). The only thing that blocks it is ICANN's 60-day registration/transfer lock, and that is shown as guidance.

operationId getDomainAuthCode

StatusDescriptionResponse body
200Codeobject
403
404

POST /v1/orgs/{orgSlug}/domains/{name}/sync

Requires member or above. The registrar is the source of truth for expiry, lock and NS. If the registrar answers that the domain is not in our account, the state is transferred_out — the only signal that a transfer has completed.

operationId syncDomain

StatusDescriptionResponse body
200Reconciled domainDomain
403
404

On this page