API keys tools
MCP tools for API keys: api_keys_create, api_keys_get, api_keys_list, api_keys_revoke, api_keys_update.
api_keys_create: Create an API keyapi_keys_get: Get an API keyapi_keys_list: List API keysapi_keys_revoke: Revoke an API keyapi_keys_update: Rename an API key
api_keys_create
Create an API key. Operation api_keys.create · Organization level · permission keys:admin · risk tier security · since M1
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"needsbrandId(or a brand-scoped request); the key acts on that brand only.kind: "entity"needsentityId; 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).
Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: false · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
name | string | yes | (1–100 characters) |
kind | one of org, entity, brand | no | (default "brand") |
entityId | ID (ent_…) | no | – |
brandId | ID (brd_…) | no | – |
scopes | array of one of 98 values, e.g. org:read, org:write, org:admin | yes | (1–100 items) |
expiresAt | date-time (ISO 8601) | no | – |
entity_id | ID (ent_…) | no | Optional: act inside this legal entity (ent_…) instead of the whole organization. |
brand_id | ID (brd_…) | no | Optional: act inside this brand (brd_…) instead of the whole organization. |
idempotency_key | string | no | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters) |
dry_run | boolean | no | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false) |
- Scope: the whole organization, or one legal entity or brand of it with
entity_idorbrand_id. - Idempotency: the result returns the
idempotency_keyused, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours). - Dry run: supported.
dry_run: truechecks permissions and rules and computes the result, then rolls everything back.
Errors
validation_failed: A field is missing or invalid, e.g. a brand key without brandId, or expiresAt in the past.api_key_scope_invalid: A scope isn't a permission, or this kind of key can't use it.api_key_scope_not_allowed: A scope is broader than what you may do at the key's brand, entity or organization.live_keys_unavailable: A live key is requested before a brand in its reach is live, or the plan or organization status doesn't allow live mode.resource_not_found: The brand or entity doesn't exist or is outside your scope.scope_mismatch: An entity or org key is requested from a narrower (brand or entity) context.permission_denied: You can't manage API keys at this target.livemode_not_allowed: You have no live-mode access, so you can't create live keys.fresh_auth_required: Your last sign-in is older than 15 minutes.
Examples
A brand key for a billing backend
Arguments:
{
"name": "Billing backend",
"brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
"scopes": ["customers:write", "subscriptions:write", "usage:write"],
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"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.
Arguments:
{
"name": "Usage ingest",
"kind": "brand",
"brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
"scopes": ["usage:write"],
"expiresAt": "2026-10-20T09:30:00.000Z",
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"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"
}
api_keys_get
Get an API key. Operation api_keys.get · Organization level · permission keys:read · risk tier read · since M1
Returns one API key by its ID (key_…): name, kind, binding, scopes, status, and when it was last used.
Never returns the secret or its hash. Keys of another mode, or outside the brand or entity of the request,
are resource_not_found.
Annotations: readOnlyHint: true · destructiveHint: false · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (key_…) | yes | – |
entity_id | ID (ent_…) | no | Optional: act inside this legal entity (ent_…) instead of the whole organization. |
brand_id | ID (brd_…) | no | Optional: act inside this brand (brd_…) instead of the whole organization. |
- Scope: the whole organization, or one legal entity or brand of it with
entity_idorbrand_id. - Read-only: changes nothing;
idempotency_keyis ignored.
Errors
resource_not_found: No key with this ID is visible in the scope and mode of the request.permission_denied: You can't see API keys here.
Example
A brand key that was used recently
Arguments:
{
"id": "key_01m4ttwd3tesktp0hc6bpxwkpd"
}
Result output:
{
"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": "2026-10-20T09:30:00.000Z",
"revokedAt": null
}
api_keys_list
List API keys. Operation api_keys.list · Organization level · permission keys:read · risk tier read · since M1
Lists the API keys you can see, newest first, in the mode of the request. Never returns secrets or hashes:
keys are recognised by prefix (their first 12 characters) and name.
An organization-level request sees every key of the organization (org, entity and brand keys); an entity
request sees the entity's keys and its brands' keys; a brand request sees only that brand's keys. Filter by
kind, entityId, brandId and status (active, expired, revoked). Paginate with limit (1–100,
default 10) and starting_after (the next_cursor of the previous page).
Annotations: readOnlyHint: true · destructiveHint: false · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
limit | integer | no | (1–100) |
starting_after | ID (key_…) | no | – |
kind | one of org, entity, brand | no | – |
entityId | ID (ent_…) | no | – |
brandId | ID (brd_…) | no | – |
status | one of active, expired, revoked | no | – |
entity_id | ID (ent_…) | no | Optional: act inside this legal entity (ent_…) instead of the whole organization. |
brand_id | ID (brd_…) | no | Optional: act inside this brand (brd_…) instead of the whole organization. |
- Scope: the whole organization, or one legal entity or brand of it with
entity_idorbrand_id. - Read-only: changes nothing;
idempotency_keyis ignored.
Errors
validation_failed: A filter or pagination value is invalid.scope_mismatch: A filter names an entity or brand outside the scope of the request.permission_denied: You can't see API keys here.
Examples
Active keys of a brand
Arguments:
{
"brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
"status": "active"
}
Result output:
{
"object": "list",
"data": [
{
"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": "2026-10-20T09:30:00.000Z",
"revokedAt": null
}
],
"has_more": false,
"next_cursor": null
}
Two keys per page
Arguments:
{
"limit": 2
}
Result output:
{
"object": "list",
"data": [
{
"id": "key_01m4ttwd3veh9apbewxheq5xh1",
"object": "api_key",
"kind": "org",
"livemode": false,
"name": "Automation",
"prefix": "or_test_acme",
"scopes": ["customers:write", "subscriptions:write", "usage:write"],
"status": "active",
"orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
"entityId": null,
"brandId": null,
"createdBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
"createdAt": "2026-10-13T12:00:00.000Z",
"updatedAt": "2026-10-13T12:00:00.000Z",
"expiresAt": null,
"lastUsedAt": null,
"revokedAt": null
},
{
"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
}
],
"has_more": true,
"next_cursor": "key_01m4ttwd3tesktp0hc6bpxwkpd"
}
api_keys_revoke
Revoke an API key. Operation api_keys.revoke · Organization level · permission keys:admin · risk tier security · since M1
Revokes an API key. It stops working immediately: every later request with it fails with api_key_invalid.
Revocation is permanent; create a new key to replace it. Revoking a key that is already revoked changes
nothing and returns it (the original revokedAt stays).
Annotations: readOnlyHint: false · destructiveHint: true · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (key_…) | yes | – |
entity_id | ID (ent_…) | no | Optional: act inside this legal entity (ent_…) instead of the whole organization. |
brand_id | ID (brd_…) | no | Optional: act inside this brand (brd_…) instead of the whole organization. |
idempotency_key | string | no | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters) |
dry_run | boolean | no | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false) |
- Scope: the whole organization, or one legal entity or brand of it with
entity_idorbrand_id. - Idempotency: the result returns the
idempotency_keyused, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours). - Dry run: supported.
dry_run: truechecks permissions and rules and computes the result, then rolls everything back.
Errors
resource_not_found: No key with this ID is visible in the scope and mode of the request.version_conflict: The key changed at the same moment; retry.permission_denied: You can't manage API keys here.
Example
Revoke a leaked key
Arguments:
{
"id": "key_01m4ttwd3tesktp0hc6bpxwkpd",
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"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": "revoked",
"orgId": "org_01m4ttwd3veh9apbewxheq5xh3",
"entityId": "ent_01m4ttwd3veh9apbewxheq5xh4",
"brandId": "brd_01m4ttwd3veh9apbewxheq5xh5",
"createdBy": "usr_01m4ttwd3veh9apbewxheq5xh6",
"createdAt": "2026-10-13T12:00:00.000Z",
"updatedAt": "2026-10-20T09:30:00.000Z",
"expiresAt": null,
"lastUsedAt": null,
"revokedAt": "2026-10-20T09:30:00.000Z"
}
api_keys_update
Rename an API key. Operation api_keys.update · Organization level · permission keys:admin · risk tier security · since M1
Changes an API key's name, the label you see in the console and request logs. Nothing else about a key
changes after creation: to change its scopes, brand or mode, create a new key and revoke the old one.
Revoked keys can't be renamed.
Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: true · openWorldHint: false
Arguments
| Argument | Type | Required | Description |
|---|---|---|---|
id | ID (key_…) | yes | – |
name | string | yes | (1–100 characters) |
entity_id | ID (ent_…) | no | Optional: act inside this legal entity (ent_…) instead of the whole organization. |
brand_id | ID (brd_…) | no | Optional: act inside this brand (brd_…) instead of the whole organization. |
idempotency_key | string | no | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters) |
dry_run | boolean | no | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false) |
- Scope: the whole organization, or one legal entity or brand of it with
entity_idorbrand_id. - Idempotency: the result returns the
idempotency_keyused, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours). - Dry run: supported.
dry_run: truechecks permissions and rules and computes the result, then rolls everything back.
Errors
validation_failed: The name is empty or longer than 100 characters.resource_not_found: No key with this ID is visible in the scope and mode of the request.api_key_revoked: The key is revoked.version_conflict: The key changed at the same moment; retry.permission_denied: You can't manage API keys here.
Example
Rename a key
Arguments:
{
"id": "key_01m4ttwd3tesktp0hc6bpxwkpd",
"name": "Billing backend (eu-west)",
"idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
Result output:
{
"id": "key_01m4ttwd3tesktp0hc6bpxwkpd",
"object": "api_key",
"kind": "brand",
"livemode": false,
"name": "Billing backend (eu-west)",
"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-20T09:30:00.000Z",
"expiresAt": null,
"lastUsedAt": null,
"revokedAt": null
}