CustomDomain · Schema
ProviderAccount
CompanyCustom DomainsDNSSSLEdge ProxySaaS InfrastructureWhite LabelMCP
Properties
| Name | Type | Description |
|---|---|---|
| needs_you | object | Why the account needs the person; absent when nothing does. The list puts these accounts first. |
| health | object | What the last check of the key found. The lifecycle sweep reads each continuous account's key once a day, and `POST /provider-accounts/{id}:check` does it on request. Absent for a one time account and |
| made_by | object | How the key was made and by whom. |
| enforced_by | string | Who holds the key to the account's scope. `provider`: the key itself reaches only the zones it was made for (a Cloudflare API token's zone resources, Porkbun's per domain API access, an IAM policy on |
| more_domains | array | The domains the key lists at the provider that the workspace has not connected, sorted: "This account holds 11 more domains". A domain counts as connected when the workspace has a connection for it or |
| id | string | |
| kind | string | |
| provider | string | |
| provider_name | string | |
| label | string | What the account is called. A key the agent made reads ` |
| access | string | |
| scope | string | |
| domains | array | The selected zones (scope `selected`). |
| credential_held | boolean | Whether the key is still kept and usable (false for a one time account past its hour). The key itself is never returned. |
| status | string | |
| last_error | string | The provider's own words about the last failure with the key (a refused key reads `The provider refused the saved key: ...`). A delegated agent token's answer always leaves it out, for every key, beca |
| created_by | string | Who connected it: the API key's name (`member: |
| last_used_at | string | |
| expires_at | string | When a one time account's key is deleted at the latest. |
| created_at | string | |
| updated_at | string | |
| connections | array | |
| uses | array | What the account's access is used for. |
| can_manage | boolean | 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. |
| application_id | string | Set for an account bound to one application: a lasting API key the cloud browser's agent made for it. Its key serves that application's domains and those of the applications in `application_ids`; conn |
| application_ids | array | The other applications of the workspace an admin shared the key with, besides `application_id`, sorted. Empty when it is shared with none, for a key bound to no application (it serves every one) and f |
| origin | string | `browser_agent` for a key the agent made after the end user signed in; absent for a key a person pasted. |
| agent_key | object | |
| owner_kind | string | Whose key it is. `workspace`: a key the workspace holds (pasted, or made at a secure sign in a member started in the console). `end_user`: a key an end user's own sign in made (in the widget, or start |
| end_user_ref | string | The platform's id for that end user, when the sign in named one. Not shown to a viewer. |
| account_ref | string | The provider account the key belongs to, as the provider names it (a customer number, a user name). Not shown to a viewer. |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/customdomain-ai/json-schema/customdomain-ai-provider-account-schema.json",
"title": "ProviderAccount",
"x-generated": "2026-11-04",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/customdomain-ai-openapi.yml#/components/schemas/ProviderAccount",
"type": "object",
"required": [
"id",
"kind",
"provider",
"provider_name",
"label",
"access",
"scope",
"domains",
"credential_held",
"status",
"connections",
"uses",
"can_manage",
"application_ids",
"made_by",
"enforced_by",
"created_at"
],
"properties": {
"needs_you": {
"type": "object",
"description": "Why the account needs the person; absent when nothing does. The list puts these accounts first.",
"required": [
"reason"
],
"properties": {
"reason": {
"type": "string",
"enum": [
"refused",
"expired",
"check_failed",
"expiring",
"one_time_window",
"no_domains"
],
"description": "`refused`: the provider refused the key; reconnect it or remove the account. `expired`: the key reached its end, or a one time window passed with the key unused. `check_failed`: the daily check of the key failed three times in a row without the provider refusing it (a timeout, a server error, a domain the key no longer reads); the key may still work, and `POST /provider-accounts/{id}:check` tries it now. `expiring`: a key made at a sign-in ends within 30 days (`until`). `one_time_window`: a one time key waits for its domains to be connected, until `until`. `no_domains`: a continuous key the workspace holds that no domain uses."
},
"until": {
"type": "string",
"format": "date-time",
"description": "When the key ends (`expiring`) or the one time window closes (`one_time_window`)."
}
}
},
"health": {
"type": "object",
"description": "What the last check of the key found. The lifecycle sweep reads each continuous account's key once a day, and `POST /provider-accounts/{id}:check` does it on request. Absent for a one time account and for one that holds no key. It names no one and no domain, so a delegated agent token reads it as a member does.",
"required": [
"state",
"failures"
],
"properties": {
"state": {
"type": "string",
"enum": [
"ok",
"failing",
"refused",
"unchecked"
],
"description": "`ok`: the last check worked. `failing`: the last check or more reached no verdict (the account joins `needs_you` as `check_failed` from the third in a row). `refused`: the provider refused the key. `unchecked`: no check has run yet."
},
"checked_at": {
"type": "string",
"format": "date-time",
"description": "When the key was last read against its provider; absent until then."
},
"failures": {
"type": "integer",
"minimum": 0,
"description": "How many checks in a row reached no verdict. The daily check backs off after each (1, 4, 12, 24, then 48 hours)."
}
}
},
"made_by": {
"type": "object",
"description": "How the key was made and by whom.",
"required": [
"how"
],
"properties": {
"how": {
"type": "string",
"enum": [
"pasted",
"console_sign_in",
"widget_sign_in",
"oauth"
],
"description": "`pasted`: a person pasted the key. `console_sign_in`: made at a secure sign-in a member started in the console. `widget_sign_in`: made at your customer's own sign-in, in the widget or one your backend started for them through the API. `oauth`: a member signed in with the company (`POST /provider-accounts:oauth-start`)."
},
"by": {
"type": "string",
"description": "A member's e-mail, `a customer` for a key your customer's sign-in made (never their id), an API key's name, or absent when it was not recorded. A delegated agent token's answer always leaves it out (an agent has no need to know which person made a key); `how` stays."
}
}
},
"enforced_by": {
"type": "string",
"enum": [
"provider",
"customdomain"
],
"description": "Who holds the key to the account's scope. `provider`: the key itself reaches only the zones it was made for (a Cloudflare API token's zone resources, Porkbun's per domain API access, an IAM policy on Route 53). `customdomain`: the key reaches the whole account at the provider, and CustomDomain™ uses it only for the domains in the scope."
},
"more_domains": {
"type": "array",
"items": {
"type": "string"
},
"description": "The domains the key lists at the provider that the workspace has not connected, sorted: \"This account holds 11 more domains\". A domain counts as connected when the workspace has a connection for it or for a name under it, in any application; a failed connection and a test mode one count for nothing. Only on `GET /provider-accounts/{id}` and on the answer of a secure sign-in's keep (`POST /browser-sessions/{sid}:keep`), and only for whoever manages the account (`can_manage`; never a viewer): listing a key's domains is a use of the key. It lists domains outside the account's scope too, which a connect refuses until the scope covers them. Empty for a provider that cannot list the domains of a key. Absent for anyone else, on the list, for a key an end user's secure sign-in made, for an account with no usable key, and when the provider could not be asked."
},
"id": {
"type": "string"
},
"kind": {
"type": "string",
"enum": [
"api_key"
]
},
"provider": {
"type": "string"
},
"provider_name": {
"type": "string"
},
"label": {
"type": "string",
"description": "What the account is called. A key the agent made reads `<Provider> key for <domain>`. A delegated agent token reads `<Provider> key` for a key made for another application and shared with its own."
},
"access": {
"type": "string",
"enum": [
"continuous",
"one_time"
]
},
"scope": {
"type": "string",
"enum": [
"all",
"selected"
]
},
"domains": {
"type": "array",
"description": "The selected zones (scope `selected`).",
"items": {
"type": "string"
}
},
"credential_held": {
"type": "boolean",
"description": "Whether the key is still kept and usable (false for a one time account past its hour). The key itself is never returned."
},
"status": {
"type": "string",
"enum": [
"active",
"used",
"expired",
"needs_reconnect"
]
},
"last_error": {
"type": "string",
"description": "The provider's own words about the last failure with the key (a refused key reads `The provider refused the saved key: ...`). A delegated agent token's answer always leaves it out, for every key, because the words can name another application's domain; `status` and `needs_you.reason` say the state."
},
"created_by": {
"type": "string",
"description": "Who connected it: the API key's name (`member:<id>` for a member's key) for a pasted key; for a key made at a secure sign-in, the member or the workspace key whose console call started it, `end_user:<ref>` or `widget:<application id>` for one the widget started, and `api:<key id>` for one an API key started without the console's signed call. Only a key a member made in the console serves the application's other domains. A delegated agent token's answer leaves it out, as it leaves out `made_by.by`."
},
"last_used_at": {
"type": "string",
"format": "date-time"
},
"expires_at": {
"type": "string",
"format": "date-time",
"description": "When a one time account's key is deleted at the latest."
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"connections": {
"type": "array",
"items": {
"$ref": "#/$defs/AccountConnection"
}
},
"uses": {
"type": "array",
"description": "What the account's access is used for.",
"items": {
"type": "string"
}
},
"can_manage": {
"type": "boolean",
"description": "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."
},
"application_id": {
"type": "string",
"description": "Set for an account bound to one application: a lasting API key the cloud browser's agent made for it. Its key serves that application's domains and those of the applications in `application_ids`; connecting any other application's domain with it is refused (`403`). A delegated agent token's answer leaves it out for a key made for another application and shared with its own."
},
"application_ids": {
"type": "array",
"description": "The other applications of the workspace an admin shared the key with, besides `application_id`, sorted. Empty when it is shared with none, for a key bound to no application (it serves every one) and for an end user's key (never shared). Change it with `updateProviderAccount`. A delegated agent token's answer leaves it empty for every key: the ids name the workspace's other applications, and the agent needs only that the key serves its own, which `application_id` says.",
"items": {
"type": "string"
}
},
"origin": {
"type": "string",
"enum": [
"browser_agent"
],
"description": "`browser_agent` for a key the agent made after the end user signed in; absent for a key a person pasted."
},
"agent_key": {
"$ref": "#/$defs/AgentKey"
},
"owner_kind": {
"type": "string",
"enum": [
"workspace",
"end_user"
],
"description": "Whose key it is. `workspace`: a key the workspace holds (pasted, or made at a secure sign in a member started in the console). `end_user`: a key an end user's own sign in made (in the widget, or started by an API key without the console's signed call); it acts only for that end user, in its application, and the workspace can narrow or remove it but never use, widen or list it."
},
"end_user_ref": {
"type": "string",
"description": "The platform's id for that end user, when the sign in named one. Not shown to a viewer."
},
"account_ref": {
"type": "string",
"description": "The provider account the key belongs to, as the provider names it (a customer number, a user name). Not shown to a viewer."
}
},
"$defs": {
"AccountConnection": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"application_id": {
"type": "string"
},
"domain": {
"type": "string"
},
"status": {
"type": "string"
}
}
},
"AgentKey": {
"type": "object",
"description": "What is kept about a lasting API key the cloud browser's agent made at a provider after the end user signed in. Never the key.",
"required": [
"scopes",
"rights"
],
"properties": {
"name": {
"type": "string",
"description": "The name the key was made with: `CustomDomain` and the application's name. A delegated agent token's answer leaves it out for every key."
},
"scopes": {
"type": "array",
"items": {
"type": "string"
},
"description": "The scopes it was made with, as the provider names them; empty for a provider whose keys have none."
},
"account": {
"type": "string",
"description": "The provider account's identifier when the page showed one (a customer number or user name). Never an email address. Absent for a viewer."
},
"session_id": {
"type": "string",
"description": "The cloud browser session that made it. Absent for a viewer."
},
"verified_at": {
"type": "string",
"format": "date-time",
"description": "When the read through the provider's API answered with it."
},
"expires_at": {
"type": "string",
"format": "date-time",
"description": "Its own end at the provider; absent for no end date."
},
"notice": {
"type": "string",
"enum": [
"d30",
"d7",
"expired"
],
"description": "The last expiry notice sent."
},
"reconnect_reason": {
"type": "string",
"enum": [
"expiring",
"expired",
"refused"
],
"description": "Why the end user is asked to sign in again."
},
"reconnect_sent_at": {
"type": "string",
"format": "date-time",
"description": "When a reconnect link was last emailed or copied."
},
"renewed_at": {
"type": "string",
"format": "date-time",
"description": "When a reconnect last swapped in a new key."
},
"old_key": {
"type": "string",
"enum": [
"revoke_by_hand"
],
"description": "`revoke_by_hand`: the key a reconnect replaced still lives at the provider; revoke it at `revoke_url`."
},
"revoke_url": {
"type": "string",
"format": "uri",
"description": "The provider's page where the key is revoked."
},
"rights": {
"type": "array",
"items": {
"type": "string",
"enum": [
"transfer",
"billing",
"account"
]
},
"description": "What the key can do beyond the domain's DNS records, so the platform knows what it holds: `transfer` (it can transfer the domain away), `billing` (it can make charges on the account: Spaceship's renewals and purchases), `account` (a key with no scopes, which holds every right the provider's API gives the account, transfers and renewals included where the API offers them). Empty for a key that reaches the DNS records only. The keys are made with every domain scope the provider offers (the owner's decision of 2026-10-20)."
}
}
}
}
}
Work with this as data
Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/customdomain-ai-provider-account"
All schemas
curl "https://apis.io/api/v1/json-schemas?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.