Custom domains for SaaS

Your product.
Their domain.

Give every customer a branded hostname without building the DNS checks, certificate jobs and hostname routing behind it.

One domain objectOne HTTPS destinationThree observable checks

A feature your users understand.

Your product stores one domain ID and renders the exact state returned by the API. The customer sees the DNS record to add; your team sees which layer needs attention.

01

Register the hostname

Create an exact subdomain or apex domain for a selected HTTPS destination.

POST /v1/domains
{ "hostname": "portal.acme.eu" }
02

Show the returned DNS record

Subdomains receive a CNAME; apex domains receive the edge IPv4 A records.

CNAME portal.acme.eu → in.subdomain.to
03

Render separate checks

DNS, certificate and routing statuses remain visible alongside the overall lifecycle.

dns_status · certificate_status · routing_status

One object, no ambiguous “pending”.

The overall status describes the workflow. Separate check fields tell support and your UI whether DNS, certificate issuance or routing is responsible.

01 · PENDING_DNS

Waiting for DNS

The expected record is returned immediately and is not visible yet.

02 · VALIDATING

Record detected

DNS matches and validation has started.

03 · PROVISIONING

Publishing HTTPS

The certificate and edge route are being prepared.

04 · ACTIVE

Traffic is live

DNS, certificate and routing checks are operational.

Domain resourceGET /domains/{id}
{
  "status": "pending_dns",
  "dns_status": "pending",
  "certificate_status": "pending",
  "routing_status": "pending"
}
One resource, four useful answers

Turn infrastructure into product copy.

The lifecycle status drives the overall workflow. The three subsystem statuses tell your UI who can act next and tell support where to investigate.

status
Which step is the customer domain in?
dns_status
Does the customer need to change DNS?
certificate_status
Is certificate issuance still progressing?
routing_status
Can the edge forward traffic?
Keep your origin

The domain layer, not another host.

Send traffic to the public HTTPS application you already operate. HTTPS destinations use port 443 or 8443; credentials, query strings, fragments and private or reserved addresses are rejected.

Customer hostname
portal.acme.eu
Edge
TLS termination + registered-host routing
HTTPS destination
https://app.yoursaas.com:443
Unknown hostname
Rejected before the destination
Application boundary

Your tenant model stays yours.

subdomain.to decides whether a registered hostname may reach the HTTPS destination. Your application still decides which tenant owns that hostname and what the request may access.

01Customer hostnameportal.acme.eu
02Edge decisionRegistered + TLS ready
03Forwarded contextX-Forwarded-Host
04Your applicationResolve + authorize tenant

Operational by design.

Build customer-facing onboarding without losing the controls your engineering and support teams need.

DNS Exact record

DNS instructions you can render.

Every creation response includes record type, name and value; no documentation detour is required.

API Retry-safe

Stable business keys.

Use an idempotency key based on your customer and domain to replay a failed network request safely.

Support Diagnosable

The failing layer is named.

Inspect the overall lifecycle status, the three subsystem statuses and the latest error instead of guessing from a single badge.

Questions before shipping

Built around the real edge cases.

Can a customer use an apex domain?

Yes. The API identifies apex domains and returns stable edge IPv4 A records instead of a CNAME.

Can customer domains target different applications?

Yes. Pass an HTTPS destination ID during customer-domain creation; omit it to use the account default.

What happens when DNS changes later?

Active domains remain part of DNS sweeps. A broken record can move to misconfigured, keeping the issue visible.

Can an unregistered hostname reach the app?

No. Routes are published only for explicitly registered hostnames after certificate validation.

First customer domain

Create the resource. Render the DNS records.

Start in the dashboard or follow the server-side quickstart. Both paths use the same customer-domain lifecycle.

Creation result
HTTP/1.1 201 Created

{
  "data": {
    "hostname": "portal.acme.eu",
    "status": "pending_dns",
    "dns_records": [{
      "type": "CNAME",
      "name": "portal.acme.eu",
      "value": "in.subdomain.to"
    }]
  }
}