---
title: "Build the one-click apply URL (sync) or start the managed async rail"
method: POST
path: "/connections/{id}/domainconnect:start"
tags: ["Connections"]
---

# Build the one-click apply URL (sync) or start the managed async rail

`POST /connections/{id}/domainconnect:start`

## Request

- Base URL: `https://api.customdomain.ai/v1`
- URL: `https://api.customdomain.ai/v1/connections/{id}/domainconnect:start`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://api.customdomain.ai/oauth/agent/authorize`, token URL `https://api.customdomain.ai/oauth/agent/token`, scopes: `domains:connect`)

**Rail A (one-click sync-redirect) by default.** `service_id` may be omitted when a default/sole template is loaded; the response carries the provider-hosted `apply_url`, the resolved `service_id`, and the discovered `dc_provider` name. Set `managed: true` (or `rail: "async"`) to request the managed async rail instead. When the provider supports it the response carries a `consent_url` and `rail: "async"` (and the grant lets the control plane re-apply / revert server-side without re-consent). `service_ids` (plural) bundles several templates under one managed consent (async only; the OAuth scope is the space-separated list and the callback applies each); on the sync fallthrough only the first template applies.

Either rail is offered only when the DNS provider holds the exact template: the control plane runs the Domain Connect template check against the provider's API first (remembered for a few minutes), and a provider that has not onboarded it is refused with a `503` that names it. A root domain uses `apex-a` (an `A` record to the edge address, which needs `APEX_A_TARGETS`). Our templates point domains at the edge, so a domain routed to your own infrastructure is refused with `422 custom_routing`. The sync `apply_url` carries a signed `redirect_uri` back to `/connect/dc/return/{state}` whenever the template allows it; pass `return_origin` on a sync start to have that return page post the outcome to your page.

A widget JWT starts either rail for its own application's connections (a domain-bound token for its own domain only); an API key for a connection of any application in its tenant, and a member's key needs a role that operates apps.

A delegated agent token needs `domains:connect` and starts the setup of its own application's connections.

## Path parameters

- `id` string, required

## Request body

- object
  - `service_id` string
  - `service_ids` string[]: Bundle of templates to authorize under one managed consent (async rail only). Wins over `service_id` when set.
  - `host` string
  - `vars` object
  - `managed` boolean: Opt into the managed (async) one-click rail.
  - `rail` string: Set to "async" to request the managed rail (same effect as managed:true).
  - `return_origin` string: Vetted web origin the finish page may postMessage the outcome to; must be on the server allowlist. Used by the async callback, and by the sync return page on a plain sync start.

## Response `200`

Sync rail returns `apply_url`; the managed async rail returns `consent_url` and `rail: "async"`.

- object
  - `apply_url` string, uri: Sync rail: provider-hosted apply URL.
  - `consent_url` string, uri: Async rail: provider consent URL.
  - `service_id` string
  - `service_ids` string[]: Async rail: the resolved template bundle.
  - `dc_provider` string
  - `rail` string: "async" on the managed rail; omitted on the sync rail.

## Other responses

- `400`: Error envelope: {code, title, details}.
- `401`: Error envelope: {code, title, details}.
- `403`: Error envelope: {code, title, details}.
- `404`: Error envelope: {code, title, details}.
- `422`: The target is a root (apex) domain that the selected template cannot serve. Branch on `code`: `apex_template_required` means the named template is `hostRequired` (or no apex-capable template is loaded): retry without `service_id`, or pass a `host` to set up a subdomain instead. `InvalidNameservers` means the domain has no usable NS delegation. `custom_routing` means the domain is routed to your own infrastructure (its `routing.mode` is `custom`) and the templates point domains at the CustomDomain™ edge: add the records manually or with a provider API key.
- `503`: Error envelope: {code, title, details}.

---

[API](https://skmtc.dev/customdomain/apis/customdomain-control-plane-api.md) · [All operations](https://skmtc.dev/customdomain/apis/customdomain-control-plane-api/llms.txt) · [OpenAPI document](https://skmtc.dev/customdomain/apis/customdomain-control-plane-api/revisions/34d89cb7a7cd?raw)
