Skip to content

Create an API key

The api_keys.create operation: POST /api/v1/api_keys in the REST API and the api_keys_create tool in the MCP server.

POST/api/v1/api_keys

Creates an API key for a brand (the default), a legal entity, or the whole organization (an org management key), in the mode of the request. The response contains the key in secret. It is shown only once: only a hash is stored, so copy it to your secret manager now. prefix (the first 12 characters) identifies the key later in the console and request logs.

  • kind: "brand" needs brandId (or a brand-scoped request); the key acts on that brand only.
  • kind: "entity" needs entityId; the key acts on the entity's brands and its ledger, filings, registrations and tasks.
  • kind: "org" acts on the whole organization, including management operations such as members, brands and API keys. It needs an organization-level request.

scopes are permission scopes such as customers:read, subscriptions:write or usage:write (a restricted key for usage writers). A key can only carry scopes its kind can use, and never more than you could do yourself at that brand, entity or organization in that mode.

Live keys (or_live_…) need a live brand (go-live checklist), a plan with live mode and an active organization; otherwise the call fails with live_keys_unavailable. Creating keys needs a sign-in within the last 15 minutes in the console, and approval for agents (security tier).

At a glance

  • REST: POST /api/v1/api_keys
  • MCP tool: api_keys_create
  • Operation ID: api_keys.create
  • Scope: Organization, or one of its legal entities or brands
  • Permission: keys:admin
  • Risk tier: security
  • Dry run: Supported (send Ownrecord-Dry-Run: true)
  • Idempotency: Idempotency-Key required
  • Modes: Test and live
  • Authentication: API key with the keys:admin scope
  • Fresh sign-in: In the console, a sign-in within the last 15 minutes
  • Since: M1

Request

Body

A JSON object (Content-Type: application/json):

FieldTypeRequiredDescription
namestringYes
kindone of org, entity, brandNo
entityIdent_… IDNo
brandIdbrd_… IDNo
scopesarray of one of 98 values, e.g. org:read, org:write, org:admin (all in the OpenAPI document)Yes
expiresAtdate-timeNo

Response

201 Created with a JSON object:

FieldTypeDescription
idkey_… ID
object"api_key"
kindone of org, entity, brand
livemodeboolean
namestring
prefixstring
scopesarray of one of 98 values, e.g. org:read, org:write, org:admin (all in the OpenAPI document)
statusone of active, expired, revoked
orgIdorg_… ID
entityIdent_… ID or null
brandIdbrd_… ID or null
createdBystring
createdAtdate-time
updatedAtdate-time
expiresAtdate-time or null
lastUsedAtdate-time or null
revokedAtdate-time or null
secretstring

Examples

A brand key for a billing backend

HTTP
POST /api/v1/api_keys
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "name": "Billing backend",
  "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
  "scopes": [
    "customers:write",
    "subscriptions:write",
    "usage:write"
  ]
}

Response (201):

JSON
{
  "id": "key_01m4ttwd3tesktp0hc6bpxwkpd",
  "object": "api_key",
  "kind": "brand",
  "livemode": false,
  "name": "Billing backend",
  "prefix": "or_test_acme",
  "scopes": ["customers:write", "subscriptions:write", "usage:write"],
  "status": "active",
  "orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
  "entityId": "ent_01m4ttwd3veh9apbewxheq5xh4",
  "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
  "createdBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-13T12:00:00.000Z",
  "expiresAt": null,
  "lastUsedAt": null,
  "revokedAt": null,
  "secret": "or_test_acme-app_ExampleOnlyNotARealKey000000000000000000000"
}

A restricted usage writer that expires

High-frequency usage writers only need usage:write.

HTTP
POST /api/v1/api_keys
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "name": "Usage ingest",
  "kind": "brand",
  "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
  "scopes": [
    "usage:write"
  ],
  "expiresAt": "2026-10-20T09:30:00.000Z"
}

Response (201):

JSON
{
  "id": "key_01m4ttwd3tesktp0hc6bpxwkpd",
  "object": "api_key",
  "kind": "brand",
  "livemode": false,
  "name": "Usage ingest",
  "prefix": "or_test_acme",
  "scopes": ["usage:write"],
  "status": "active",
  "orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
  "entityId": "ent_01m4ttwd3veh9apbewxheq5xh4",
  "brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
  "createdBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-13T12:00:00.000Z",
  "expiresAt": "2026-10-20T09:30:00.000Z",
  "lastUsedAt": null,
  "revokedAt": null,
  "secret": "or_test_acme-app_ExampleOnlyNotARealKey000000000000000000000"
}

Errors

CodeHTTP statusWhenWhat to do
validation_failed400A field is missing or invalid, e.g. a brand key without brandId, or expiresAt in the past.Fix the fields listed in details.issues and send the request again.
api_key_scope_invalid400A scope isn't a permission, or this kind of key can't use it.Use permission scopes from the catalogue ({resource}:{read|write|admin}, e.g. customers:read) that this kind of key can use. details.problems lists each scope and why.
api_key_scope_not_allowed403A scope is broader than what you may do at the key's brand, entity or organization.Remove the scopes listed in details.problems, or ask an organization owner or admin to create the key.
live_keys_unavailable400A live key is requested before a brand in its reach is live, or the plan or organization status doesn't allow live mode.Create a test-mode key, or complete the brand's go-live checklist (console → brand → Go live) and try again.
resource_not_found404The brand or entity doesn't exist or is outside your scope.Check the ID and that your credentials are scoped to the right organization, entity, brand and mode.
scope_mismatch403An entity or org key is requested from a narrower (brand or entity) context.Use credentials scoped to that organization, entity or brand, or leave the scope fields out of the request.
permission_denied403You can't manage API keys at this target.Ask an organization owner or admin for a role or scope that allows this action.
livemode_not_allowed403You have no live-mode access, so you can't create live keys.Use test mode, or credentials for the target's mode. Developers need live access granted by an organization owner or admin.
fresh_auth_required403Your last sign-in is older than 15 minutes.Sign in again, then repeat the action within 15 minutes.

It can also return these common errors: api_version_unsupported, invalid_json, unsupported_media_type, authentication_required, api_key_invalid, idempotency_key_required, idempotency_key_reused, idempotency_in_progress, approval_required, approval_rejected, approval_expired, stale_approval, approval_policy_denied, rate_limited, internal_error.