API reference
Domains
Add, check, redirect, move and remove custom domains, and connect Cloudflare by sign-in or API token.
See Domains for the DNS record to add and how a domain moves from pending through verifying to active.
GET /v1/orgs/:orgId/domains
Lists custom domains, and target: the hostname to point their CNAME records at.
Auth: user access token or platform agent key · Scope: domains:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
domains: {
message?: string
status?: "error" | "active" | "pending" | "verifying"
createdAt?: number
updatedAt?: number
orgId: string
projectId: string
hostname: string
tenantId?: string
certificateArn?: string
records?: string
zone?: string
dnsProvider?: string
checkedAt?: number
redirectTo?: string
}[]
target: string
}POST /v1/orgs/:orgId/domains
Adds a custom domain to a project and returns the DNS record to create.
Auth: user access token or platform agent key · Scope: domains:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
hostname | string | Yes | matches ^(?=.{4,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$; lowercased |
projectId | string | Yes |
Response 201
{
domain: {
message?: string
status?: "error" | "active" | "pending" | "verifying"
createdAt?: number
updatedAt?: number
orgId: string
projectId: string
hostname: string
tenantId?: string
certificateArn?: string
records?: string
zone?: string
dnsProvider?: string
checkedAt?: number
redirectTo?: string
}
records: {
type: "CNAME" | "TXT"
name: string
value: string
}[]
dns?: {
ok: boolean
expected: string
found: string[]
}
}Errors
| Status | Message |
|---|---|
400 | Platform hostnames can't be added as custom domains. |
404 | Project not found |
409 | This domain is already in use. |
502 | Couldn't set up this domain. Try again. |
POST /v1/orgs/:orgId/domains/:hostname/verify
Checks the domain's certificate and updates its status.
Auth: user access token or platform agent key · Scope: domains:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:hostname | The custom domain. |
Response 200
{
domain: {
message?: string
status?: "error" | "active" | "pending" | "verifying"
createdAt?: number
updatedAt?: number
orgId: string
projectId: string
hostname: string
tenantId?: string
certificateArn?: string
records?: string
zone?: string
dnsProvider?: string
checkedAt?: number
redirectTo?: string
}
}
| {
domain: {
message?: string
status?: "error" | "active" | "pending" | "verifying"
createdAt?: number
updatedAt?: number
orgId: string
projectId: string
hostname: string
tenantId?: string
certificateArn?: string
records?: string
zone?: string
dnsProvider?: string
checkedAt?: number
redirectTo?: string
}
dns: {
ok: boolean
expected: string
found: string[]
}
}Errors
| Status | Message |
|---|---|
404 | Domain not found |
POST /v1/orgs/:orgId/domains/:hostname/cloudflare
Creates the domain's records with the org's connected Cloudflare token, then checks right away.
Auth: user access token or platform agent key · Scope: domains:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:hostname | The custom domain. |
Response 200
{
domain: {
message?: string
status?: "error" | "active" | "pending" | "verifying"
createdAt?: number
updatedAt?: number
orgId: string
projectId: string
hostname: string
tenantId?: string
certificateArn?: string
records?: string
zone?: string
dnsProvider?: string
checkedAt?: number
redirectTo?: string
}
dns: {
ok: boolean
expected: string
found: string[]
}
}Errors
| Status | Message |
|---|---|
400 | This domain's zone couldn't be found in DNS. |
400 | Connect Cloudflare first. |
404 | Domain not found |
PATCH /v1/orgs/:orgId/domains/:hostname
Moves a domain to another project of the org, or makes it redirect to another domain of its project (redirectTo: null serves the project again). The edge route changes right away.
Auth: user access token or platform agent key · Scope: domains:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:hostname | The custom domain. |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
projectId | string | No | at least 1 character |
redirectTo | string | No | matches ^(?=.{4,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$; lowercased; can be null |
Response 200
{
domain: {
message?: string
status?: "error" | "active" | "pending" | "verifying"
createdAt?: number
updatedAt?: number
orgId: string
projectId: string
hostname: string
tenantId?: string
certificateArn?: string
records?: string
zone?: string
dnsProvider?: string
checkedAt?: number
redirectTo?: string
}
}Errors
| Status | Message |
|---|---|
400 | A domain can't redirect to itself. |
400 | Redirect to another domain of the same project. |
400 | … redirects too. Choose a domain that serves the project. |
404 | Domain not found |
404 | Project not found |
409 | … redirects to this domain. Change that first. |
DELETE /v1/orgs/:orgId/domains/:hostname
Removes a custom domain: its route and its certificate.
Auth: user access token or platform agent key · Scope: domains:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
:hostname | The custom domain. |
Response 204 with no body.
Errors
| Status | Message |
|---|---|
404 | Domain not found |
409 | … redirects to this domain. Change that first. |
GET /v1/orgs/:orgId/integrations/cloudflare
Whether Cloudflare is connected (by sign-in or API token), the zones it can see, whether a sign-in grant expired, and whether sign-in is available. Credentials are never returned.
Auth: user access token or platform agent key · Scope: domains:read
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 200
{
connected: boolean
kind: null | "token" | "oauth"
zones: string[]
connectedAt?: number
expired: boolean
oauth: boolean
}POST /v1/orgs/:orgId/integrations/cloudflare/authorize
Starts the OAuth flow: stores a one-time state and returns Cloudflare's authorize URL.
Auth: user access token or platform agent key · Scope: domains:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Request body
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
returnTo | string | No | up to 500 characters | |
offline | boolean | No | true |
Response 200
{
url: string
}Errors
| Status | Message |
|---|---|
403 | Connecting Cloudflare needs a signed-in user. |
501 | Cloudflare sign-in isn't available. Use an API token instead. |
POST /v1/orgs/:orgId/integrations/cloudflare/oauth
Completes the OAuth flow. The state is consumed first (one use), then checked against this user and org. With error instead of code (the user declined), it only consumes the state and returns where to go back to; retry says to start again without offline access.
Auth: user access token or platform agent key · Scope: domains:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
state | string | Yes | 10–300 characters |
code | string | No | 1–2,000 characters |
error | string | No | up to 200 characters |
Response 200
{
connected: false
returnTo: string
retry: boolean
}
| {
connected: true
zones: string[]
returnTo: string
refresh: boolean
}Errors
| Status | Message |
|---|---|
422 | Cloudflare didn't share any zones. Choose the zones you'll use when you allow access. |
501 | Cloudflare sign-in isn't available. |
PUT /v1/orgs/:orgId/integrations/cloudflare
Connects a Cloudflare API token (Zone → DNS → Edit) for adding domain records. The token is checked against Cloudflare, encrypted and stored; it must see at least one zone.
Auth: user access token or platform agent key · Scope: domains:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
token | string | Yes | 20–200 characters; trimmed |
Response 200
{
connected: true
kind: string
zones: string[]
}Errors
| Status | Message |
|---|---|
400 | The token can't see any zones. Give it Zone → DNS → Edit on the zones you'll use. |
DELETE /v1/orgs/:orgId/integrations/cloudflare
Disconnects Cloudflare: revokes a sign-in grant at Cloudflare (best effort) and deletes the stored credentials.
Auth: user access token or platform agent key · Scope: domains:write
| Path parameter | Description |
|---|---|
:orgId | Organization id (org_…). |
Response 204 with no body.