# Add a provider account by secure sign in (the console only)

> Add a provider account by secure sign in (the console only): CustomDomain™ API reference. Lists request parameters, the request body, responses and error codes.

Source: https://docs.customdomain.ai/docs/api-reference/provider-accounts/startProviderAccountSignIn

## `POST https://api.customdomain.ai/v1/provider-accounts:sign-in`

**The console only.** Starts the secure sign in that adds a provider account with no domain: the person signs in to the provider in a temporary browser, the agent makes a lasting API key on the provider's own key page, and CustomDomain™ checks the key by listing the domains it reaches. The key then waits in memory for the keep step, which makes the account only after the person confirmed which of those domains it may use (`POST /browser-sessions/{sid}:keep`, within ten minutes). Nothing is kept before that: no `provider_accounts` row exists, and a sign in that is abandoned or left to run out names the key it made so the person can delete it at the provider (`left_key`).

Only the console's own call starts one: an API key that carries the console's signed visitor forward, naming the person signed in to it. The `X-CustomDomain-Client` header and the `Origin` are labels any key holder can send, so neither counts alone, and a widget token, an end user's token, a delegated agent token and the operator's key are refused with `403` `browser_account_unavailable`. The caller must also hold a role that operates applications (an owner, an admin or a member; a viewer is `403` `forbidden`), and the request must carry an `Origin` on the server's return origin allowlist, as `browser:start` requires. A workspace an operator suspended starts none, as it starts no other cloud browser (`403` `workspace_suspended`).

Only a provider whose key can be made at sign in and whose domains can be listed qualifies (`account_ways` of `GET /providers` names `secure_sign_in` for it); any other is `403` `browser_provider_not_allowed` or `409` `browser_account_unavailable`. One sign in at a time runs for a member and a provider (`409` `browser_session_active`), and three start an hour.

Returns the address of the popup page, whose fragment carries a single use bootstrap code that no server sees; the popup trades it at `POST /browser-sessions:redeem`. The answers of every call about the session are `Cache-Control: no-store`.

### Authentication

`apiKey`

### Request body (JSON)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `provider` | string | yes | The provider id. An account has no domain to detect it from. |
| `application_id` | string | no | The application the key is for, one of the workspace's own live applications (a test mode application is refused, and another workspace's is `404`). Left out, the key serves the whole workspace and takes no share. |
| `return_origin` | string | yes | Web origin the popup posts its result to; must be on the server's allowlist. |
| `consent_version` | `cb-1`, `cb-2`, `cb-3`, `cb-4` | yes | The id of the consent text the person was shown, as for `browser:start`. |
| `locale` | string | no | The language the popup reads in |
| `viewport_hint` | object | no | The size of the popup's live area, used as for `browser:start`. |

### Responses

| Status | Description |
| --- | --- |
| `201` | The sign in started. |
| `400` | Error envelope: {code, title, details}. |
| `401` | Error envelope: {code, title, details}. |
| `403` | `browser_account_unavailable` (not the console's own call, or not a caller that may), `browser_customer_present_only` (no known `Origin`), `browser_provider_not_allowed`, `sandbox_not_allowed` (a test mode application) or `forbidden` (a viewer). |
| `404` | Error envelope: {code, title, details}. |
| `409` | Error envelope: {code, title, details}. |
| `422` | Error envelope: {code, title, details}. |
| `429` | Error envelope: {code, title, details}. |
| `503` | Error envelope: {code, title, details}. |

### `201` response body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `session_id` | string | yes | The session id, `bs_` and 32 hex characters. |
| `popup_url` | string | yes | The popup page; its fragment holds the single use bootstrap code. |

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