Docs / For AI coding agents

For AI coding agents

A compact, complete brief for AI coding agents integrating Custom Domain API into a SaaS codebase. Contracts, invariants, and a step-by-step checklist.

Give this page to your coding assistant, or point it at https://customdomainapi.com/docs/ai-agents.md. Everything an integration needs is below, with links to the full pages.

Goal

Let each workspace (tenant) of a SaaS app serve the app on a hostname its customer owns, such as forms.acme.com, over HTTPS.

Facts

  • API base URL: https://edge.customdomainapi.com/v1 on the Free plan, otherwise https://<edge name>/v1. Auth: Authorization: Bearer <API key>.
  • OpenAPI: https://edge.customdomainapi.com/v1/openapi.json.
  • Python SDK: pip install custom-domain-sdk (custom_domain.Client, CustomDomainMiddleware, WorkspaceResolver, verify_webhook).
  • Customers CNAME their hostname to edge.customdomainapi.com on Free.
  • Secrets the app needs (from app.customdomainapi.com, each shown once): CUSTOM_DOMAIN_API_KEY, CUSTOM_DOMAIN_ASSERTION_SECRET with its key id (app_…), CUSTOM_DOMAIN_APPLICATION_ID, and a webhook secret if webhooks are used. Read them from the environment; never commit them.

Invariants (do not break)

  1. Never select the tenant from the Host header. Select it from the verified X-Custom-Domain-Assertion (ref field) only. See Verifying requests.
  2. Verify the assertion before trusting it: HMAC-SHA256, key looked up by id, constant-time compare, exp/iat with 30 s skew, app equals the application id, host equals the request host.
  3. Serve GET /.well-known/custom-domain-workspace returning {"reference": "<ref from the verified assertion>"} (404 if the workspace doesn’t exist). The domain can’t go live without it.
  4. Store the domain id with the workspace; show the customer the dns_records exactly as returned.
  5. Send Idempotency-Key on POST /v1/domains so retries are safe.
  6. Treat webhooks as at-least-once and unordered: verify the signature, dedupe on event id, compare created_at.
  7. Handle 409 hostname_already_claimed, 409 domain_limit_reached, 422 apex_not_supported and the other 422 hostname codes with clear messages to the customer; respect 429 Retry-After.

Checklist

  1. Data model: add to the workspace (or a new table) custom_hostname, custom_domain_id, custom_domain_status.
  2. Settings UI: a field for the hostname. On save, call POST /v1/domains with hostname and reference = the workspace id; store id and status; render the two dns_records with copy buttons.
  3. Status: show status and each failing check’s message. A “check again” button calls POST /v1/domains/{id}/checks.
  4. Updates: subscribe to domain.ready, domain.attention_required, domain.recovered and domain.deleted (POST /v1/webhooks), and update the stored status in the handler; or poll GET /v1/domains/{id}.
  5. Removing: DELETE /v1/domains/{id} when the customer removes the hostname or the workspace is deleted.
  6. Request routing: add the assertion verification middleware; map ref to the workspace for every request that carries the header. Requests on the app’s own domain (no header) keep their existing routing.
  7. Absolute URLs: build them from the request’s Host and X-Forwarded-Proto; the edge sets both to the customer-facing values. Cookies should not set a Domain attribute bound to the app’s own domain.
  8. Tests: a forged or expired assertion is refused; a valid one selects the right workspace; Host alone never selects a workspace.

Full pages

Quickstart · How it works · API reference · Verifying requests · Webhooks · Your customers’ DNS