# Add a provider account by signing in with the company (the console only)

> start provider account o auth: CustomDomain™ API reference in the provider accounts group. Covers parameters, request body, responses and error codes.

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

## `POST https://api.customdomain.ai/v1/provider-accounts:oauth-start`

**The console only.** Starts "Sign in with <company>", the way to add a provider account with no domain by the company's own OAuth consent screen. It answers the address to open in a popup. When the person approves access there, the shared sign-in callback (`GET /connect/oauth/callback`) makes the account: every domain the sign-in reaches, continuous access, with the access token and the refresh token kept encrypted (a token near its end is refreshed before it is used). The popup posts `{ok, purpose: "account", provider, account_id}` to `return_origin`, or `{ok: false, code, message}` when the person declined or it failed (`access_denied`, `oauth_failed`, `oauth_scope_not_granted`, `oauth_no_refresh`, `ProviderAuthenticationError`, `account_check_failed`); a token the account did not keep is revoked at the company. Signing in again to the same account (DNSimple's account, a Vercel team) renews the account it made before instead of adding a second one.

The state binds the workspace, the member who started it and the application, is single use and lives ten minutes. Nothing is written before the callback.

Offered only where `account_ways` of `GET /providers` names `oauth` for the company: the deployment runs the company's OAuth app, keeps what it hands back (`OAUTH_MANAGED_PROVIDERS` and a grant encryption key), does not hold the sign-in back, and the company's sign-in needs no domain. Any other is `403` `oauth_account_unavailable`. The caller is the console's own call, as for `POST /provider-accounts:sign-in`: an API key that carries the console's signed visitor forward, held by a member who operates applications (`403` `browser_account_unavailable` otherwise; a viewer is `403` `forbidden`). A workspace an operator suspended starts none (`403` `workspace_suspended`).

### 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 account 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 account serves the whole workspace. |
| `return_origin` | string | yes | Web origin the popup posts its result to; must be on the server's allowlist. |

### Responses

| Status | Description |
| --- | --- |
| `200` | The sign-in started; open `authorize_url` in a popup. |
| `400` | Error envelope: {code, title, details}. |
| `401` | Error envelope: {code, title, details}. |
| `403` | Error envelope: {code, title, details}. |
| `404` | Error envelope: {code, title, details}. |
| `503` | Error envelope: {code, title, details}. |

### `200` response body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `authorize_url` | string | yes | The company's consent page (or Vercel's install page). |
| `provider` | string | yes |  |
| `flow` | `oauth2`, `vercel_integration` | yes | The sign-in the company runs. |
| `callback_origin` | string | yes | The origin the result is posted from; accept a message from no other. |

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