Custom domains
Covers the 4 API operations in the hostnames category.
| Method | Path | Description |
|---|---|---|
| GET | /v1/orgs/{orgSlug}/projects/{projectName}/hostnames | List the domains connected to a project (runlot domain list) |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/hostnames | Connect a custom domain (runlot domain add) |
| DELETE | /v1/orgs/{orgSlug}/projects/{projectName}/hostnames/{host} | Disconnect a custom domain (runlot domain rm) |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/hostnames/{host}/verify | Verify a domain now (runlot domain verify) |
GET /v1/orgs/{orgSlug}/projects/{projectName}/hostnames
The default hostname (kind: default) and custom domains (kind: custom) are returned together. A custom domain record includes the guidance records (verify) and its state (docs/domains.md §3.2). Requires viewer or above.
operationId listHostnames
| Status | Description | Response body |
|---|---|---|
| 200 | List | HostnameList |
| 403 | — | — |
| 404 | — | — |
POST /v1/orgs/{orgSlug}/projects/{projectName}/hostnames
The name is normalized to lowercase punycode before it is stored. Wildcards and names under our own domains (*.runlot.app·*.runlot.dev· the app domain) are not accepted.
The record is created in the pending_dns state and reserves that name from that moment on. While verification is in progress no other project can use the same name. Until it is connected it is not in the routing table, so requests to that name get a 404 unknown_hostname.
If the same project sends the same name again, the existing row is returned unchanged (idempotent) — if the token changed, the TXT record already in place would become wrong at that moment. Requires member or above. Audit hostname.add.
operationId addHostname
Request body: application/json · object
| Status | Description | Response body |
|---|---|---|
| 200 | The newly created or already existing record | Hostname |
| 400 | Not a valid name shape (bad_request), a wildcard, or under one of our own domains | Error |
| 403 | — | — |
| 404 | — | — |
| 409 | The name is already in use by another project. code is hostname_taken | Error |
DELETE /v1/orgs/{orgSlug}/projects/{projectName}/hostnames/{host}
Deletes the Cloudflare custom hostname together with the managed record in the runlot DNS zone. The default hostname cannot be deleted (400). It is the address the deployment defines, so deleting it here leaves the project unreachable until the next deploy. Requires member or above. Audit hostname.delete.
operationId deleteHostname
| Status | Description | Response body |
|---|---|---|
| 204 | Revoked | — |
| 400 | It is the default hostname | Error |
| 403 | — | — |
| 404 | — | — |
POST /v1/orgs/{orgSlug}/projects/{projectName}/hostnames/{host}/verify
Runs the same check as the background job (every minute), immediately. Ownership passes if any one of three conditions holds: the name is inside our zone and belongs to the same org, the _runlot-verify.<host> TXT record matches, or the CNAME of <host> points at the fallback origin.
There is no path to active without proof of ownership. If the check does not pass, the state stays as it is and lastError carries what is visible right now. Requires member or above.
operationId verifyHostname
| Status | Description | Response body |
|---|---|---|
| 200 | The row after verification | Hostname |
| 403 | — | — |
| 404 | — | — |