Domain forwarding
Redirect a connected domain to another URL, or send the apex to www, with a 301 issued at the edge that keeps the path and query and never contacts your origin.
Domain forwarding turns a connected domain into a redirect instead of a proxied
origin. When a customer wants oldbrand.example (or a bare apex) to send visitors
somewhere else, the edge answers the request with an HTTP 301 Moved Permanently
and never contacts an origin.
What it does
There are two forms, both resolved on the edge's hot path right after the ask gate approves the host:
- Redirect to a target URL. The connection carries a redirect target; every
request for the domain 301s to that URL. The incoming request's path and
query are preserved, so
https://old.example/a/b?x=1lands onhttps://new.example.com/a/b?x=1. - Apex → www. For a bare apex host (e.g.
example.com), the edge 301s to thewww.counterpart (https://www.example.com/…), again preserving path + query. A request already onwww.is proxied normally, so there is no redirect loop.
Because the 301 is emitted at the edge, the customer's origin never sees the request and no certificate on the origin side is required for the old hostname (only the edge cert, which is issued automatically once the domain is live).
From the console
Open the domain, then its Settings tab (a domain's settings).
Forwarding is a field: type an https:// address and Save, or Clear to stop forwarding.
www redirect, for a root domain, is a switch with its own Save. After a save the tab says what it did.
For the www redirect that is whether we wrote the www record for you or you add it where you manage DNS (the
record is shown, with a link to the DNS tab). Members, admins and owners can change them; a viewer reads them.
Enabling it with the API (edge-served)
Forwarding is part of the Power feature set and is driven by the control plane: the redirect target
(redirect_to) and the apex→www flag (www_redirect) are attributes of the connection. Change them with
PATCH /v1/connections/{id} (API reference), or with
POST /v1/connections/{id}/power (and POST /v1/connections/{id}/power:repower to change a connection that
is already powered; omitting application_url there keeps the current origin):
curl -X PATCH https://api.customdomain.ai/v1/connections/<ID> \
-H "Authorization: Bearer $CUSTOMDOMAIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "redirect_to": "https://new.example.com" }'Send "redirect_to": "" to clear a redirect. The edge picks up the intent within one ask-cache TTL, with no
redeploy. When neither is set, the domain is proxied to its origin as usual.
- The plan.
redirect_toneeds edge serving, which is included on Growth, Premium and Enterprise: on Starter and Startup, setting or changing it returns402with the codeplan_upgrade_required(clearing one never does).www_redirectis on every plan, andclient_labeltoo. Where the deployment has edge serving off,redirect_toreturns503. - Who may call it. An API key of a member, admin or owner, or a token with the
appscope for a connection of its own application. A viewer's key, an end user's widget token (its own connection too) and a delegated agent token are refused with403; the target of a redirect decides where a domain's visitors go, so the platform that owns the domain decides it. - The address is checked.
redirect_tomust be a plainhttps://address of a public domain.400 invalid_requestnames the reason when it is nothttps(http:,javascript:,data:and an address with no scheme are all refused), when it holds a user name or password (https://[email protected]), when it is an IP address or a name that cannot be reached from the internet (localhost,.local,.internal,.test), or when it holds spaces, backslashes or hidden characters. The port is read as a number and stored once::443is dropped, and:0443is the same port, so it is the domain itself when it names the domain. A target that names the domain on port 80 is the domain itself too, as the edge reads it.422 redirect_target_not_allowedis a domain another CustomDomain™ workspace has connected or claimed, whether or not it is serving yet: two workspaces could forward to each other and neither could see the circle. A domain your own workspace serves is yours to forward to, whoever else has a pending or failed claim on it.422 redirect_loopis an address that would send a visit round in a circle: the domain itself, or a chain through thewwwredirect and your other forwards that comes back to a host it went through (taking a forward off a domain whosewwwredirect is on counts: the visit then goes to thewwwname), or a chain of more than 8 forwards in a row (the title then says "too many forwards"). The answer names only the domains you can see, your workspace's and, for anapptoken, its own application's; any other reads "another domain". If a check cannot read who owns the address's domain, the answer is500and nothing is stored. The same checks apply toredirect_toon/powerand/power:repower. An address equal to the one already set is not checked again. - Two requests at once. Redirect changes of one workspace are made one at a time, each checked against the
domains as they are when its turn comes, so two changes made together cannot make a circle between them: the
second answers
422 redirect_loop. A change that waits too long for its turn answers503with the coderedirects_busyand aRetry-Afterheader, and changes nothing: send it again. A request writes only the settings it changes, and a value it sends back as it read it is not a change, so a setting another request has changed since is not undone.DELETE /v1/connections/{id}/powerclears the forward and the root path access through the same checks: on a domain whosewwwredirect is on, taking the forward off is refused (422 redirect_loop) whenwwwforwards back to the root. A domain that is being removed answers409to all of these, also when the removal starts while the change waits. - The www redirect and its record.
www_redirectis for a root domain only (422 www_redirect_apex_onlyfor a subdomain). Turning it on adds awwwrecord to the records the domain needs. A zone CustomDomain™ hosts is rewritten at once, and a domain whose records were written through a connected provider account is rewritten whenmove_rewriteis on. For any other domain the response hascustomer_action_required: trueandconnection.records_outdatedis sent, and the person adds the record. The domain stays live meanwhile. Turning it off also stops the edge answering forwww.that domain, unless it is a connection of its own. - Test mode. A test mode domain takes
client_labelonly; the two redirects answer403 sandbox_not_allowed. - The audit log. Every change is recorded as
connection.updated, with the before and after of the fields that changed, by the member or key that made it (widget:<application id>for anapptoken). A domain that is being removed answers409. The redirects are stored before the name: if onlyclient_labelcannot be written, the answer is500, the redirect change is stored and recorded, and sending the same body again writes the name.
The redirect template (provider-written)
When the domain runs on a provider that implements the one-click (Domain
Connect) protocol, forwarding can instead be written at the provider. The
redirect service template (serviceName: "Forward this domain") declares a
single REDIR301 record on the apex (@) whose target is the redirectTarget
variable:
{ "type": "REDIR301", "host": "@", "target": "%redirectTarget%", "ttl": 3600 }REDIR301 is a pseudo-record native to the Domain Connect protocol (like
SPFM): the provider's forwarding feature (not our edge) issues the 301 to
redirectTarget, preserving path and query. A companion apex-www template
covers the apex→www case the same way.
Only the one-click (Domain Connect) rail can apply the redirect template.
The OAuth and API-token rails refuse any template carrying a REDIR301/
REDIR302 record with forwarding_not_supported: a redirect is HTTP behavior,
not a DNS record, and a provider's DNS API has no way to write one. Before the
guard, the literal REDIR301 was handed to the provider's DNS API and the
poller then marked the connection live off a write that configured nothing. On
those rails, serve the redirect from the edge instead (the section above), or
set forwarding manually in the provider's own control panel. (The apex-www
template is unaffected: it writes an apex A record plus a www CNAME, both of
which those rails apply; the edge issues the apex→www redirect.)
Widget forwarding path
The widget applies forwarding through the ordinary one-click setup rail, using the same
POST /v1/connections/{id}/domainconnect:start call it uses for connection
records, but naming the redirect template and passing the destination as a
variable:
curl -X POST https://api.customdomain.ai/v1/connections/<ID>/domainconnect:start \
-H "Authorization: Bearer <WIDGET_JWT>" \
-d '{"service_id":"redirect","vars":{"redirectTarget":"https://new.example.com"}}'
# → 200 { apply_url, service_id: "redirect", dc_provider }redirectTarget must be an http or https URL, or a bare host, at a public
hostname (not an IP address, localhost or an internal name), with no user name
or password; anything else answers 400 invalid_request naming it, and the
redirect template takes no other variable (see
Template variables).
The response's apply_url is opened in the provider popup; once the customer
approves, the provider writes the REDIR301 record and the propagation poller
promotes the connection to live. Choose this path when the domain stays on its
current provider; choose the edge-served redirect_to / www_redirect above when
the domain is proxied through the edge.
End user notices
Give CustomDomain™ the end user's email, from your server or the widget: after a Move they get one email with the new DNS records, and a reconnect email when their provider's API key needs them, sent on your behalf.
Managed connections
Opt a connection into managed mode so the control plane can re-apply and revert its records with a stored, encrypted grant, and see which providers support it.