コンテンツにスキップ

Mint a personal access token.

POST
/api/v1/api-tokens
curl --request POST \
--url https://example.com/api/v1/api-tokens \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "expires_at": "2026-04-15T12:00:00Z", "name": "example", "owner_user_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "role": "viewer", "scope": "All", "surfaces": [ "mcp" ] }'

The raw token is in this response and nowhere else — only its hash is stored, so no later call can produce it again.

The token acts as an account (owner_user_id, defaulting to the caller): disabling or deleting that account stops the token, and its role is capped at the owner’s current role on every use. For anything unattended, own it with a service account rather than a person — see POST /api/v1/users — so the credential does not depend on who happened to create it.

Media typeapplication/json

Request body for POST /api/v1/api-tokens.

object
expires_at

When the token stops working. Omit for no expiry — appropriate for a service account driving an integration, and deliberately still allowed.

string | null format: date-time
name
required

Human label (unique, ≤128 chars).

string
owner_user_id

The account the token acts as. Omit to own it yourself; name a service account for anything unattended, so the credential outlives whoever set it up.

string | null format: uuid
role
required

The role the token grants (viewer is the right default for a read-only client). Capped at the owner’s role on every use, so this is a ceiling rather than a promise.

string
Allowed values: viewer operator admin
scope
One of:
null
surfaces

Which surfaces the token may authenticate. Defaults to ["mcp"] when omitted, matching what every token issued before this field existed can do.

Array<string> | null
Allowed values: mcp rest

Token minted; token is the raw bearer and is returned only here

Media typeapplication/json

The one and only response carrying a usable token.

A named type rather than an inline json! because of what the token field is: the client has to store it now, since only its hash is kept and no later call can produce it again. Giving it a type makes that field visible in one place if this response ever grows a second consumer.

object
expires_at
string | null format: date-time
id
required
string format: uuid
name
required
string
role
required

Predefined roles, ordered least → most privileged.

string
Allowed values: viewer operator admin
surfaces
required
Array<string>
Allowed values: mcp rest
token
required

The raw bearer token, returned once. Never stored, never logged.

string
Example
{
"role": "viewer",
"surfaces": [
"mcp"
]
}

Bad name, a scope naming no groups or a group that does not exist, a scope on a token whose owner is itself group-scoped, no surface named, an expiry already in the past, or an owner id that names no account

Media typeapplication/json

The ADR-019 envelope every failure renders as. pub(crate) and schema-bearing so the OpenAPI document can name one error shape for every endpoint (ADR-035) instead of leaving 4xx/5xx bodies undescribed — a client that has to guess the failure shape ends up parsing the success shape and reading undefined.

object
error
required
object
code
required

Stable machine-readable code. Clients branch on this, never on the message.

string
message
required

Operator-facing sentence. Safe to display; never carries an internal error’s own text.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example"
}
}

No valid bearer token

Media typeapplication/json

The ADR-019 envelope every failure renders as. pub(crate) and schema-bearing so the OpenAPI document can name one error shape for every endpoint (ADR-035) instead of leaving 4xx/5xx bodies undescribed — a client that has to guess the failure shape ends up parsing the success shape and reading undefined.

object
error
required
object
code
required

Stable machine-readable code. Clients branch on this, never on the message.

string
message
required

Operator-facing sentence. Safe to display; never carries an internal error’s own text.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example"
}
}

Role below Admin

Media typeapplication/json

The ADR-019 envelope every failure renders as. pub(crate) and schema-bearing so the OpenAPI document can name one error shape for every endpoint (ADR-035) instead of leaving 4xx/5xx bodies undescribed — a client that has to guess the failure shape ends up parsing the success shape and reading undefined.

object
error
required
object
code
required

Stable machine-readable code. Clients branch on this, never on the message.

string
message
required

Operator-facing sentence. Safe to display; never carries an internal error’s own text.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example"
}
}

An API token with that name already exists

Media typeapplication/json

The ADR-019 envelope every failure renders as. pub(crate) and schema-bearing so the OpenAPI document can name one error shape for every endpoint (ADR-035) instead of leaving 4xx/5xx bodies undescribed — a client that has to guess the failure shape ends up parsing the success shape and reading undefined.

object
error
required
object
code
required

Stable machine-readable code. Clients branch on this, never on the message.

string
message
required

Operator-facing sentence. Safe to display; never carries an internal error’s own text.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example"
}
}

Skeleton mode has no token store

Media typeapplication/json

The ADR-019 envelope every failure renders as. pub(crate) and schema-bearing so the OpenAPI document can name one error shape for every endpoint (ADR-035) instead of leaving 4xx/5xx bodies undescribed — a client that has to guess the failure shape ends up parsing the success shape and reading undefined.

object
error
required
object
code
required

Stable machine-readable code. Clients branch on this, never on the message.

string
message
required

Operator-facing sentence. Safe to display; never carries an internal error’s own text.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example"
}
}