# Begin the cloud browser sign in for a connection

> Begin the cloud browser sign in for a connection: CustomDomain™ API reference in the cloud browser group. Covers parameters, request body and responses.

Source: https://docs.customdomain.ai/docs/api-reference/cloud-browser/startConnectionBrowser

## `POST https://api.customdomain.ai/v1/connections/{id}/browser:start`

**Customer present only.** For a DNS provider with no sign in of its own, the customer signs in to the provider inside a temporary browser that a browser hosting company runs for a few minutes. They type their own username, password and any verification code into the provider's real sign in page, so CustomDomain™ never receives them, and the sign in itself is never stored. Where the deployment turned it on for the provider, the agent then makes a lasting API key on the provider's own API page (named `CustomDomain` and the application's name, with the domain and DNS scopes only and the longest expiry the provider offers), checks it with one read only call, keeps it encrypted for this application only, and writes the records through the provider's API; the domain is then monitored and repaired like any connected provider account, and the connection's `credential` shows the key's record (never the key). Otherwise, or when making the key fails, our software reads the provider's DNS page for this one domain, shows the customer the exact changes, and makes them only after the customer approves. A session never runs without the customer present.

With `mode: reconnect`, the session is the end user's sign in that renews the connection's lasting API key (when it nears its end or the provider stopped accepting it): the agent makes a new key with the same scopes, checks it and swaps it in, and changes no DNS record. A connection without such a key is refused with `browser_reconnect_unavailable`. A reconnect link (`POST /connections/{id}:reconnect-link`) opens the hosted page in this mode.

Returns the address of the popup page that shows the browser. Its fragment carries a single use bootstrap code, which no server sees; the popup trades it at `POST /browser-sessions:redeem`. Only an end user's widget token (bound to the domain and to the end user) or the console may start one: an agent, the MCP server and a plain API key are refused with `browser_customer_present_only`. The request must carry an `Origin` header on the server's return origin allowlist. A browser sends one (the widget and the popup do), and the console's server must add it to the call it makes for a customer. A request with no `Origin` at all, such as a server to server call, is refused with `browser_customer_present_only` and a message that says the header is missing; an `Origin` that is not on the list is refused the same way.

A record set an integrator supplied, and any type or value the provider's page cannot write, is refused before the customer signs in (`browser_unsupported_records`, with the types named). The rail is offered only for a provider that has no sign in of its own, and only while the deployment has it on (`rails.cloud_browser` on the domain check).

### Authentication

`widgetJWT`, `apiKey`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes |  |

### Request body (JSON)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `provider` | string | yes | DNS provider id; defaults to the detected provider. |
| `return_origin` | string | yes | Web origin the popup posts its result to; must be on the server's allowlist. |
| `consent_version` | string | yes | The id of the consent text the customer was shown, stored with the session. |
| `locale` | string | no | The language the popup reads in, a plain code such as `en`. Defaults to `en`. |
| `purpose` | `""`, `nameservers` | no | `nameservers` starts the session for the connection's nameserver migration (path `agent`) instead of its records: the plan is to turn DNSSEC off, or to set the exact new nameservers, and the agent may open only those controls. Refused with `409` unless the migration is waiting for a sign in (`waiting_for: browser_session`). Empty or omitted: the records. |
| `viewport_hint` | object | no | Optional. The size of the popup's live area, so the provider's sign in page fills it at full size. The remote browser is created at this width when it is a whole number from 360 to 720 and at this height when it is a whole number from 480 to 800; a side outside its range is ignored and the provider's default is used for it. The desktop popup (680 by 760) sends 695 by 716. Leave it out for the default. |
| `mode` | `connect`, `reconnect` | no | `connect` (the default) connects the domain. `reconnect` renews the lasting API key CustomDomain™ made for this connection, for the key's own provider, and changes no DNS record; the session ends `done` when the new key is in place. |
| `widget_session_id` | string | no | Optional. The widget's own session id (the `session_id` of its funnel beacons, 8 to 64 of `[A-Za-z0-9_-]`). It is recorded on the cloud browser session and the widget session of the same application is linked to it, so a sign in's outcome can be read against the device and place it ran for. It changes nothing about the session; a value that is not a session id is ignored. |

### Responses

| Status | Description |
| --- | --- |
| `200` | The session was created. |
| `400` | Error envelope: {code, title, details}. |
| `401` | Error envelope: {code, title, details}. |
| `403` | `browser_customer_present_only` (an agent, the MCP server, a plain API key, a request with no `Origin` header, or an `Origin` that is not on the return origin allowlist) or `browser_provider_not_allowed` (the rail is not offered for this provider or workspace, or the provider has a sign in of its own), or `workspace_suspended` (CustomDomain™ support suspended the workspace; see the `ForbiddenOrSuspended` response). |
| `404` | Error envelope: {code, title, details}. |
| `409` | `browser_session_active`: a secure sign in is already running for this domain, or `browser_reconnect_unavailable`: `mode: reconnect` for a connection that has no lasting API key CustomDomain™ made, or whose provider cannot make one now. |
| `422` | `browser_unsupported_records`: the record set cannot be written through the provider's page. `types` names what is in the way. |
| `429` | `browser_rate_limited`: too many starts for this domain or workspace. `Retry-After` says when the window turns. |
| `503` | `browser_unavailable` (not configured, switched off or paused), `browser_busy` (the browser vendor answered that it is busy right now; try again after `Retry-After`) or `browser_capacity` (the vendor is not answering, or a limit of sessions or monthly minutes is reached). Offer the manual steps. |

### `200` response body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `session_id` | string | yes | The session id, `bs_` and 32 hex characters. |
| `open_url` | string | yes | The popup page, with `#c=<bootstrap code>&l=<locale>` in its fragment. |
| `vendor` | string | yes | The browser hosting company, shown to the customer. |
| `expires_at` | string | yes | The latest the session can end. |

The full specification is served at `GET https://api.customdomain.ai/v1/openapi.json`.
