---
title: "Connect a provider account with a key"
method: POST
path: "/provider-accounts"
tags: ["Provider accounts"]
---

# Connect a provider account with a key

`POST /provider-accounts`

## Request

- Base URL: `https://api.customdomain.ai/v1`
- URL: `https://api.customdomain.ai/v1/provider-accounts`
- Auth: HTTP bearer

Keeps a DNS provider or registrar key for the workspace, encrypted (GRANT_ENCRYPTION_KEY; `503` without it). The key is checked first by listing the provider's domains, or, for a provider that cannot list them, by reading one of the selected domains or `check_domain`; with neither, `400` `check_domain_required`, and a key is never kept unchecked. `access` is `continuous` (kept until revoked, used only to put back records it wrote that disappear where the deployment has automatic repair on, remove records when a domain is removed, and re-apply the records it wrote on request) or `one_time` (usable for an hour, and deleted as soon as the chosen domains are connected or the hour passes). `scope` is `all` of the account's domains or `selected` ones. The key is never returned.

Anyone whose role operates applications may connect a key, read the accounts and revoke one. Changing an account's access, scope or domains, connecting domains with it and replacing its key take an admin, an owner or the member who connected it (`can_manage`).

## Request body

- object
  - `provider` string, required
  - `label` string
  - `access` 'continuous' | 'one_time'
  - `scope` 'all' | 'selected'
  - `domains` string[]
  - `check_domain` string: A domain the key manages, read to check the key when the provider cannot list its domains and `scope` is `all`.
  - `credential` object, required
    - `token` string, required
    - `params` object

## Response `201`

The account, and the provider's domains when it lists them

- object
  - `account` ProviderAccount
    - `id` string, required
    - `kind` 'api_key', required
    - `provider` string, required
    - `provider_name` string, required
    - `label` string, required
    - `access` 'continuous' | 'one_time', required
    - `scope` 'all' | 'selected', required
    - `domains` string[], required: The selected zones (scope `selected`).
    - `credential_held` boolean, required: Whether the key is still kept and usable (false for a one time account past its hour). The key itself is never returned.
    - `status` 'active' | 'used' | 'expired' | 'needs_reconnect', required
    - `last_error` string
    - `created_by` string
    - `last_used_at` string, date-time
    - `expires_at` string, date-time: When a one time account's key is deleted at the latest.
    - `created_at` string, date-time, required
    - `updated_at` string, date-time
    - `connections` AccountConnection[], required
      - `id` string
      - `application_id` string
      - `domain` string
      - `status` string
    - `uses` string[], required: What the account's access is used for.
    - `can_manage` boolean, required: Whether the caller may change the account's access, scope or domains, connect domains with it and replace its key: an admin, an owner, or the member who connected it.
  - `zones` string[]

## Other responses

- `400`: Error envelope: {code, title, details}.
- `401`: Error envelope: {code, title, details}.
- `403`: Error envelope: {code, title, details}.
- `422`: The provider refused the key (`ProviderAuthenticationError`)
- `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)
