Domains
Add your customers' hostnames, read the record each one needs and where it stands, re-check it, remove it.
Base URL https://api.apexly.dev. Send your key as Authorization: Bearer sk_live_… or sk_test_…; the examples read it from APEXLY_API_KEY.
Add a domain
POST/v1/domains
201 with the new domain in pending_dns, or 200 with the existing one when the app already has this hostname (idempotent on app + hostname; an expired one is re-added: back to pending_dns with the same connect link and a fresh 72 h window). The mode comes from the key: test keys create test domains, which never contact a CA. 422 invalid_hostname, hostname_is_apexly, hostname_is_public_suffix, hostname_held, domain_limit_reached (live domains at the plan hard cap: 2× included, 3 on Free, Growth during the 14-day trial; error.status_detail lists { plan, trial, used, limit, hostname, plans[] } that fit one more. New accounts: 10 in the first 24 hours), origin_not_allowed, validation_failed (metadata over 4 KB, apex_redirect on a subdomain, hostname already in the app in the other mode). origin needs the Scale plan; other plans ignore it and the response carries warnings.
Body
| Field | Type | Description |
|---|---|---|
hostname | string | Required. The customer's hostname, e.g. careers.acme.com (Unicode is encoded). At most 1024 characters. |
origin | string | null | Per-domain origin override (Scale and Enterprise plans; other plans: ignored with a warning). At most 2048 characters. |
metadata | object | null | Any JSON object, at most 4 KB; returned on every domain object and event. |
apex_redirect | string | Apex domains only: also serve www.<apex> and redirect it (default: the app's apex_redirect_default). One of none, www. |
Response
200 OK: the hostname already exists in this app · 201 Created. Errors use the error envelope.
| Field | Type | Description |
|---|---|---|
id | string | dom_… |
hostname | string | Lowercase ASCII (punycode). |
status | string | One of pending_dns, verifying, issuing, active, dns_broken, cert_failed, expired, held, deleted. |
status_reason | string | null | Machine code when status is not active, e.g. dns_record_mismatch. |
status_detail | object | null | { expected, found, hint }. |
is_apex | boolean | |
mode | string | From the key that created it; test domains never contact a CA. One of live, test. |
dns | object | Record names are relative to the registrable domain (e.g. "careers" in acme.com). |
dns.cname | object | Subdomains: the one record to add. |
dns.cname.name | string | |
dns.cname.value | string | |
dns.apex | object | Apex domains: A (and AAAA) records plus the _apexly TXT record. |
dns.apex.a | string[] | |
dns.apex.aaaa | string[] | |
dns.apex.txt | object | |
dns.apex.txt.name | string | |
dns.apex.txt.value | string | |
origin | string | null | Origin override, or null for the app origin. |
apex_redirect | string | One of none, www. |
connect_url | string | The page the customer opens to connect the domain. |
certificate | object | null | |
certificate.issuer | string | |
certificate.not_before | string | |
certificate.not_after | string | |
certificate.renews_at | string | |
metadata | object | null | |
created_at | string | |
updated_at | string | |
last_checked_at | string | null | |
next_check_at | string | null | |
warnings | object[] | Present when part of the request was ignored, e.g. origin on a plan without per-domain origins. |
warnings[].code | string | |
warnings[].message | string |
Example
curl -X POST https://api.apexly.dev/v1/domains \
-H "Authorization: Bearer $APEXLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"hostname":"careers.acme.com"}'List domains
GET/v1/domains
Newest first (created_at desc), cursor-paginated: pass next_cursor as cursor. Filters: status, hostname (prefix), metadata.<key>=<value> (string equality on a top-level key, up to 5).
Query parameters
| Field | Type | Description |
|---|---|---|
status | string | One of pending_dns, verifying, issuing, active, dns_broken, cert_failed, expired, held, deleted. |
hostname | string | Hostname prefix. At most 253 characters. |
limit | integer | Default 50. 1 to 100. |
cursor | string | next_cursor of the previous page. At most 200 characters. |
Response
200 OK. Errors use the error envelope.
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].id | string | dom_… |
data[].hostname | string | Lowercase ASCII (punycode). |
data[].status | string | One of pending_dns, verifying, issuing, active, dns_broken, cert_failed, expired, held, deleted. |
data[].status_reason | string | null | Machine code when status is not active, e.g. dns_record_mismatch. |
data[].status_detail | object | null | { expected, found, hint }. |
data[].is_apex | boolean | |
data[].mode | string | From the key that created it; test domains never contact a CA. One of live, test. |
data[].dns | object | Record names are relative to the registrable domain (e.g. "careers" in acme.com). |
data[].dns.cname | object | Subdomains: the one record to add. |
data[].dns.cname.name | string | |
data[].dns.cname.value | string | |
data[].dns.apex | object | Apex domains: A (and AAAA) records plus the _apexly TXT record. |
data[].dns.apex.a | string[] | |
data[].dns.apex.aaaa | string[] | |
data[].dns.apex.txt | object | |
data[].origin | string | null | Origin override, or null for the app origin. |
data[].apex_redirect | string | One of none, www. |
data[].connect_url | string | The page the customer opens to connect the domain. |
data[].certificate | object | null | |
data[].certificate.issuer | string | |
data[].certificate.not_before | string | |
data[].certificate.not_after | string | |
data[].certificate.renews_at | string | |
data[].metadata | object | null | |
data[].created_at | string | |
data[].updated_at | string | |
data[].last_checked_at | string | null | |
data[].next_check_at | string | null | |
next_cursor | string | null |
Example
curl https://api.apexly.dev/v1/domains \
-H "Authorization: Bearer $APEXLY_API_KEY"Get a domain
GET/v1/domains/{id}
Another app’s domain, or a deleted one, is 404.
Path parameters
| Field | Type | Description |
|---|---|---|
id | string |
Response
200 OK. Errors use the error envelope.
| Field | Type | Description |
|---|---|---|
id | string | dom_… |
hostname | string | Lowercase ASCII (punycode). |
status | string | One of pending_dns, verifying, issuing, active, dns_broken, cert_failed, expired, held, deleted. |
status_reason | string | null | Machine code when status is not active, e.g. dns_record_mismatch. |
status_detail | object | null | { expected, found, hint }. |
is_apex | boolean | |
mode | string | From the key that created it; test domains never contact a CA. One of live, test. |
dns | object | Record names are relative to the registrable domain (e.g. "careers" in acme.com). |
dns.cname | object | Subdomains: the one record to add. |
dns.cname.name | string | |
dns.cname.value | string | |
dns.apex | object | Apex domains: A (and AAAA) records plus the _apexly TXT record. |
dns.apex.a | string[] | |
dns.apex.aaaa | string[] | |
dns.apex.txt | object | |
dns.apex.txt.name | string | |
dns.apex.txt.value | string | |
origin | string | null | Origin override, or null for the app origin. |
apex_redirect | string | One of none, www. |
connect_url | string | The page the customer opens to connect the domain. |
certificate | object | null | |
certificate.issuer | string | |
certificate.not_before | string | |
certificate.not_after | string | |
certificate.renews_at | string | |
metadata | object | null | |
created_at | string | |
updated_at | string | |
last_checked_at | string | null | |
next_check_at | string | null |
Example
curl https://api.apexly.dev/v1/domains/dom_01J9X8T4Q5M6N7P8R9S0V1W2X3 \
-H "Authorization: Bearer $APEXLY_API_KEY"Update a domain
PATCH/v1/domains/{id}
origin (Scale plan; null removes the override; other plans ignore it with warnings), metadata (replaces the object; null removes it), apex_redirect (apex domains only).
Path parameters
| Field | Type | Description |
|---|---|---|
id | string |
Body
| Field | Type | Description |
|---|---|---|
origin | string | null | Per-domain origin override (Scale and Enterprise plans; other plans: ignored with a warning). At most 2048 characters. |
metadata | object | null | Any JSON object, at most 4 KB; returned on every domain object and event. |
apex_redirect | string | Apex domains only. One of none, www. |
Response
200 OK. Errors use the error envelope.
| Field | Type | Description |
|---|---|---|
id | string | dom_… |
hostname | string | Lowercase ASCII (punycode). |
status | string | One of pending_dns, verifying, issuing, active, dns_broken, cert_failed, expired, held, deleted. |
status_reason | string | null | Machine code when status is not active, e.g. dns_record_mismatch. |
status_detail | object | null | { expected, found, hint }. |
is_apex | boolean | |
mode | string | From the key that created it; test domains never contact a CA. One of live, test. |
dns | object | Record names are relative to the registrable domain (e.g. "careers" in acme.com). |
dns.cname | object | Subdomains: the one record to add. |
dns.cname.name | string | |
dns.cname.value | string | |
dns.apex | object | Apex domains: A (and AAAA) records plus the _apexly TXT record. |
dns.apex.a | string[] | |
dns.apex.aaaa | string[] | |
dns.apex.txt | object | |
dns.apex.txt.name | string | |
dns.apex.txt.value | string | |
origin | string | null | Origin override, or null for the app origin. |
apex_redirect | string | One of none, www. |
connect_url | string | The page the customer opens to connect the domain. |
certificate | object | null | |
certificate.issuer | string | |
certificate.not_before | string | |
certificate.not_after | string | |
certificate.renews_at | string | |
metadata | object | null | |
created_at | string | |
updated_at | string | |
last_checked_at | string | null | |
next_check_at | string | null | |
warnings | object[] | Present when part of the request was ignored, e.g. origin on a plan without per-domain origins. |
warnings[].code | string | |
warnings[].message | string |
Example
curl -X PATCH https://api.apexly.dev/v1/domains/dom_01J9X8T4Q5M6N7P8R9S0V1W2X3 \
-H "Authorization: Bearer $APEXLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"metadata":{"customer":"acme"}}'Delete a domain
DELETE/v1/domains/{id}
Emits domain.deleted; routing is dropped within 5 seconds; the hostname can be added again at once.
Path parameters
| Field | Type | Description |
|---|---|---|
id | string |
Response
204 No Content. Errors use the error envelope.
Example
curl -X DELETE https://api.apexly.dev/v1/domains/dom_01J9X8T4Q5M6N7P8R9S0V1W2X3 \
-H "Authorization: Bearer $APEXLY_API_KEY"Check a domain now
POST/v1/domains/{id}/verify
Queues a DNS check right away instead of waiting for the next scheduled one; on a cert_failed domain it retries issuance (after re-checking CAA when that was the reason). One per 15 seconds per domain (429 rate_limited with Retry-After). 422 validation_failed when there is nothing to check (issuing, held, expired, or a test domain).
Path parameters
| Field | Type | Description |
|---|---|---|
id | string |
Response
202 Accepted. Errors use the error envelope.
| Field | Type | Description |
|---|---|---|
queued | boolean | One of true. |
Example
curl -X POST https://api.apexly.dev/v1/domains/dom_01J9X8T4Q5M6N7P8R9S0V1W2X3/verify \
-H "Authorization: Bearer $APEXLY_API_KEY"