Docs / Quickstart

Quickstart

Let a customer of your SaaS use their own hostname in about fifteen minutes on the Free plan, from sign-up to HTTPS, with the API and the Python SDK.

This guide takes one customer hostname from nothing to live over HTTPS, on the Free plan. You need a backend reachable on the internet over HTTPS (your origin), and a way to run a few lines of code.

1. Start Free

Sign in at app.customdomainapi.com with your email, open Free and start. No card is needed. Your application is set up in a few seconds.

On Free, your customers point their hostnames at:

edge.customdomainapi.com

and your backend calls the API at:

https://edge.customdomainapi.com/v1

2. Add and verify your origin

On the Origin tab, add your backend’s hostname, for example app.yourproduct.com. The page shows a token and a URL. Make your origin answer that URL with exactly the token as a plain-text body:

GET https://app.yourproduct.com/.well-known/custom-domain-origin-verification
→ 200, body: <the token>

Then press Verify and use. Traffic for your customers’ hostnames goes to this origin from now on.

3. Get your assertion key

On the same tab, press Get your assertion key. You see, once:

  • the key id (it starts with app_),
  • the secret,
  • your application id.

Store the secret with your origin’s secrets. Every request the edge forwards carries an X-Custom-Domain-Assertion header signed with this key; your origin verifies it and selects the workspace from it (step 6).

4. Create your API key

On API keys, create your key. It is shown once. Free includes one key, which may make 60 requests a minute. Store it in your backend’s secrets, for example as CUSTOM_DOMAIN_API_KEY.

5. Register a customer’s hostname

When a customer enters their hostname in your product, register it for their workspace:

curl -X POST https://edge.customdomainapi.com/v1/domains \
  -H "Authorization: Bearer $CUSTOM_DOMAIN_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: signup-ws_8f3a1c" \
  -d '{"hostname": "forms.acme.com", "reference": "ws_8f3a1c"}'

Or with the Python SDK (pip install custom-domain-sdk):

from custom_domain import Client

client = Client("https://edge.customdomainapi.com", credential=CUSTOM_DOMAIN_API_KEY)
domain = client.create_domain(
    "forms.acme.com",            # the customer's exact subdomain
    reference="ws_8f3a1c",       # your workspace id; it comes back on every request
    idempotency_key="signup-ws_8f3a1c",
)
print(domain.render_dns_instructions())

The response contains dns_records: one TXT record that proves the customer owns the name and one CNAME that sends its traffic to the edge. Show both to your customer exactly as returned (see Your customers’ DNS).

6. Verify requests at your origin

Your origin must select the workspace from the verified assertion, never from the Host header. With the Python SDK in FastAPI or Starlette:

import os
from custom_domain import CustomDomainMiddleware

app.add_middleware(
    CustomDomainMiddleware,
    keys={"app_…": os.environ["CUSTOM_DOMAIN_ASSERTION_SECRET"]},  # your key id and secret
    application_id="…",                                           # your application id
    workspace_lookup=load_workspace,  # returns the workspace for a reference, or None
)

@app.get("/")
def home(request):
    workspace = load_workspace(request.state.custom_domain.reference)

The middleware also answers GET /.well-known/custom-domain-workspace, which the service calls through the edge to prove that the hostname reaches the right workspace before it goes live. Other languages: see Verifying requests.

7. Wait for ready

Once your customer has published the records, the service checks ownership, routing, the certificate and your origin. When all four pass, the domain’s status becomes ready and the hostname is served over HTTPS. Poll GET /v1/domains/{id}, or subscribe to the domain.ready webhook. If your customer fixes a record, ask for an early re-check with POST /v1/domains/{id}/checks.

That’s it. Repeat step 5 for every customer hostname, up to 25 on Free.