Docs / How it works

How it works

How Custom Domain API verifies a customer's hostname, issues its certificate and routes each request to the right workspace, and what each domain status and check means.

The path of a request

  1. TLS. A visitor opens https://forms.acme.com. The customer’s CNAME sends them to the edge, which presents a certificate for that exact hostname. Certificates are issued from Let’s Encrypt on demand, only for hostnames that passed verification, and renewed automatically.
  2. Route. The edge finds the application the hostname belongs to. A hostname that belongs to no application gets a 404 and never reaches an origin.
  3. Assert. The edge removes any X-Custom-Domain-* header the visitor sent, checks that the domain may be served right now, and adds a fresh signed X-Custom-Domain-Assertion naming your application, the domain and the workspace reference.
  4. Proxy. The request goes to your origin with Host set to the customer’s hostname and X-Forwarded-Proto: https, so absolute URLs, cookies and redirects your app builds are correct.

Your origin verifies the assertion and selects the workspace from its reference (Verifying requests). It never trusts the Host header to pick a tenant.

The four checks

A domain goes live only when all four checks pass. They are re-checked regularly, and serving stops the moment one fails.

Check Passes when
ownership The TXT record _custom-domain-challenge.<hostname> holds this registration’s token.
routing The hostname’s CNAME chain ends at your edge name (on Free, edge.customdomainapi.com).
certificate The edge serves a valid certificate for the hostname.
origin Your origin is verified, and answers GET /.well-known/custom-domain-workspace through the edge with the workspace it selected from the assertion.

Each check has a status (pending, passing or failing) and, when failing, a stable error_code and a message in plain words:

Check error_code Meaning
ownership txt_record_not_found No TXT record at that name yet.
ownership txt_token_mismatch A TXT record exists, but not with this registration’s value.
ownership txt_token_stale The TXT holds the token of an earlier registration.
routing cname_not_found No CNAME, or A/AAAA records instead of a CNAME.
routing cname_target_mismatch The CNAME points somewhere else.
either dns_timeout DNS didn’t answer; retried automatically.
origin origin_not_ready No verified origin yet.
origin workspace_probe_failed The workspace path didn’t answer 200.
origin workspace_probe_invalid It answered 200 without a JSON reference.
origin workspace_mismatch The origin selected another workspace: it isn’t using the assertion.

Failing checks are retried after 1, 2, 5, 15 and 30 minutes, then hourly; passing ones every 6 hours. Ask for an early re-check with POST /v1/domains/{id}/checks after your customer fixes a record.

Statuses

Status Meaning Served
pending_dns Waiting for the TXT and CNAME records. no
provisioning Records verified; certificate and origin checks running. no
ready All four checks pass. yes
attention_required A check that passed is failing again (often a changed CNAME). no
suspended Ownership lost for 24 hours, or suspended by policy. no
deleting Deleted. The hostname can be registered again at once. no

ready, attention_required, recovering to ready, and deletion each send a webhook.