Custom Domain docs
Connect flow

Managed connections

Opt a connection into managed mode so the control plane can silently re-apply and revert its records with a stored, encrypted grant.

Most connections are use-once: a rail writes the desired records a single time and the platform keeps no credential. Managed mode is the opt-in exception. When a connection is managed, the control plane holds a durable, encrypted async grant — issued through the provider-hosted one-click protocol — for the customer's provider, so it can re-apply or revert the template server-side — without asking the customer to re-consent.

What "managed" means

  • Opt-in only. A connection is never managed by default. It becomes managed when the customer completes the async one-click consent flow — start it with POST /v1/connections/{id}/domainconnect:start with {"managed": true} (equivalently {"rail":"async"}). When the provider supports the async variant, the response is an async consent URL; otherwise the call falls through to the ordinary sync apply_url and the connection stays use-once.
  • Encrypted grant, pinned base. The async callback (GET /v1/connect/dc/callback) exchanges the code for a durable grant against the provider API base that was pinned into the signed state at start — never re-derived from fresh discovery — and stores it encrypted at rest. The customer's browser token from the sync/OAuth rails is not this; those are discarded immediately.
  • Silent re-apply. With the grant in hand the platform can recompute the connection's authoritative desired records and push any drift through the provider's async one-click API on demand, with no customer interaction.
  • Auto-heal-ready. Because re-apply is a single server-side call, managed connections are the substrate for automatic drift healing: when Monitor reports that a record was removed or repointed, a managed connection can be pushed back to its desired state instead of only emitting a domain.record_missing alert.

The connection detail response carries a managed boolean so your dashboard can tell the two kinds apart (false is omitted on the wire). You enable managed mode by running the async consent flow above. You can turn it back off in two ways: keep the domain connected but drop the grant with disable managed (DELETE /v1/connections/{id}/grant), or take the domain off entirely by disconnecting it.

Re-apply on demand

curl -X POST http://localhost:8080/v1/connections/<ID>:reapply \
  -H "Authorization: Bearer <WIDGET_JWT>"
# → 200 { "connection_id": "<ID>", "reapplied": true, "records": [ … ] }
#   (records re-written at the provider; connection re-verified)

The 200 body is a re-apply receipt, not a connection object: it carries connection_id (not id) plus the record set that was written. Fetch GET /v1/connections/{id} if you need the connection itself.

POST /v1/connections/{id}:reapply is managed mode only. It recomputes the desired record set, writes any drift through the stored grant, re-verifies the connection, and emits connection.records.updated. If the connection is not managed or has no stored grant, it responds 409.

If the push fails it emits connection.reapply.failed. When the provider reports the grant was revoked (a 401 kill-switch — the customer withdrew consent at their provider), the platform clears the stored grant and flags the connection for re-consent; the next :reapply returns 409 until the customer re-authorizes.

A 401 isn't automatically treated as a revocation, though: an expired access token looks identical to a revoked one. Before giving up, the platform rotates the grant's access token (grant_type=refresh_token against the provider) and retries the push once with the fresh token. Only a 401 that survives a refresh (or a grant with no refresh token) is treated as a real revocation. This means a managed connection keeps re-applying silently across ordinary token expiry, and only asks the customer to re-consent when access was actually withdrawn.

Fleet-wide re-apply (drift after an edge change)

Separately from per-connection :reapply, an operator can run a fleet-wide reconciliation pass that re-drives every connection still on an older "desired-record" generation — for example after the edge's target hostname changes. For a managed connection this re-applies the template through the stored grant with no customer interaction, exactly like :reapply above. A non-managed connection has no stored credential to push through, so instead it emits a connection.records_outdated webhook carrying a prefilled heal/reconnect link — it does not rewrite the customer's DNS for you. This pass is operator-triggered, not a background guarantee: treat connection.records_outdated as a real event your integration can receive, not as something that fires on a fixed schedule.

Managed lifecycle events

Subscribe to these on a webhook endpoint to track the managed lifecycle:

EventFires when
connection.records.updatedA :reapply succeeded — the desired records were (re-)written and the connection re-verified.
connection.reapply.failedA :reapply push failed; if the grant was revoked, the connection is flagged for re-consent.
connection.disconnectedThe connection was disconnected — for a managed connection the template was reverted through the grant first.
connection.records_outdatedA fleet-wide reconciliation pass found a non-managed connection on an older desired-record generation; carries a heal/reconnect link since the platform has no credential to push the update itself.

Disabling managed mode

To stop managing a connection without disconnecting it, drop the stored grant:

curl -X DELETE http://localhost:8080/v1/connections/<ID>/grant \
  -H "Authorization: Bearer <WIDGET_JWT>"
# → 200 { "connection_id": "<ID>", "managed": false }

DELETE /v1/connections/{id}/grant deletes the encrypted async grant and clears the connection's managed flag, leaving the connection and its applied records in place. The records the provider already wrote stay live; the platform simply stops holding a credential to re-apply or revert them, so the connection reverts to the default use-once posture. A later async consent can re-enable managed mode.

This is deliberately not DELETE /v1/connections/{id} — that path reverts the template at the provider and removes the whole connection (see below). Here nothing is reverted and the connection survives. The call is idempotent: a connection that is already unmanaged returns 200 with managed: false. It does not emit a webhook event.

Ending a managed connection

To take a managed domain off your product, disconnect it with DELETE /v1/connections/{id}. For a managed connection the platform first reverts the applied template through the stored grant, then deletes the connection and all its child state (records, origin, monitor watch, and the grant itself), and emits connection.disconnected.

On this page