Apply records & go live
The three automatic rails, the manual fallback, propagation to live, and cert issuance.
Once a connection exists, get its desired records
into the customer's DNS via one of the four
rails. All of them move the
connection pending → propagating → live.
Rail C — OAuth into the provider (flagship)
curl -X POST http://localhost:8080/v1/connections/<ID>/oauth:start \
-H "Authorization: Bearer <WIDGET_JWT>" \
-H "Content-Type: application/json" \
-d '{"return_origin":"https://app.acme.example"}'
# → { "authorize_url": "https://<provider>/authorize?..." }The widget opens authorize_url in a popup. The provider redirects the customer
to GET /v1/connect/oauth/callback, which consumes the HMAC-signed single-use
state, exchanges the code, writes the records with the one-time access
token (discarded immediately, never stored), and returns an HTML page that
postMessages { type: "customdomain:oauth", payload } to the vetted
return_origin. The connection is now propagating.
Rail A — Domain Connect
curl -X POST http://localhost:8080/v1/connections/<ID>/domainconnect:start \
-H "Authorization: Bearer <WIDGET_JWT>" \
-H "Content-Type: application/json" \
-d '{}'
# → { "apply_url": "https://<provider>/domainconnect/...", "service_id": "...", "dc_provider": "..." }Redirect the customer to apply_url; their provider applies the signed template.
Both the synchronous redirect and the asynchronous variant are supported.
service_id may be omitted when a single/default template is loaded.
Rail B — API token (BYO)
The customer pastes a scoped provider token; it writes the records once and is never persisted:
curl -X POST http://localhost:8080/v1/connections/<ID>/apply \
-H "Authorization: Bearer <WIDGET_JWT>" \
-H "Content-Type: application/json" \
-d '{
"provider": "cloudflare",
"zone": "customer.com",
"credential": { "token": "<scoped-provider-token>" },
"records": [ { "type": "CNAME", "host": "app", "value": "edge.customdomain.ai", "ttl": 3600 } ]
}'SPFM records are merged into any existing SPF TXT at write time (never
clobbered); mark a record essential: true to fail the apply if it can't be
written.
Manual
If no automatic rail is available, show the records from
GET /v1/connections/{id}/records for the customer to add by hand. Nothing else
is required — the poller watches for them.
Watch propagation → live
You don't poll the API for propagation — the control-plane's background poller
(running automatically on a 1-minute interval) resolves each desired record
against public DNS and, when they all match their intended values, flips the
connection to live.
On that transition the edge issues the TLS certificate on the next handshake and
a connection.live webhook fires (exactly once). Read
current state any time with GET /v1/connections/{id}.
A propagating connection whose records never appear within 24 hours becomes
failed (and fires connection.failed). Manual pending connections don't time
out — a customer may take days.