Skip to content

Mint a CLI API token

POST
/v1/tokens
curl --request POST \
--url https://beta-api.plune.ai/v1/tokens \
--header 'Content-Type: application/json' \
--cookie plune_session=<plune_session> \
--data '{ "scope": "read" }'

Account → API tokens on the dashboard (api.ts → createToken). The body is optional: {"scope": "read" | "write"} (#1283), and none is a write token. A token is the account’s, not a named thing, and it writes for good to the project X-Plune-Project names — the one picked beside Generate — else to your default one; a project you are not in answers 404, one you only read 403. The plaintext comes back once, in this response, and is what goes into PLUNE_TOKEN for the CLI and into {{token}} in the collection; the server keeps only its hash. Session-only on purpose: a leaked API token must not be able to mint more of them. An account holds at most limit live tokens (see GET /v1/tokens) — past it the answer is 409, and revoking one is the only way on.

Media type application/json
object
scope

What a token may do (#1283). read answers GET, HEAD and OPTIONS (and POST /v1/test-cases/resolve, which only reads) and refuses every other request with 403 read-only token, each refusal written to the audit log as an api_token entry of action event (the token, the method and the path). write is everything its owner may do, and is what every token issued before this existed holds. Whatever its scope, a token that names a session in X-Plune-Session (an agent) is refused every DELETE with 403 agent_cannot_delete (#1280): a deletion is confirmed by a person. A token without the header, and a person with a session cookie, are not held.

string
Allowed values: read write
Example
{
"scope": "read"
}

Created — plaintext token shown once

Media type application/json

The token plaintext is returned ONCE, here; the server stores only its sha256.

object
id
required
string format: uuid
token
required
string
scope

What a token may do (#1283). read answers GET, HEAD and OPTIONS (and POST /v1/test-cases/resolve, which only reads) and refuses every other request with 403 read-only token, each refusal written to the audit log as an api_token entry of action event (the token, the method and the path). write is everything its owner may do, and is what every token issued before this existed holds. Whatever its scope, a token that names a session in X-Plune-Session (an agent) is refused every DELETE with 403 agent_cannot_delete (#1280): a deletion is confirmed by a person. A token without the header, and a person with a session cookie, are not held.

string
Allowed values: read write
prefix
required

Display prefix (first chars) — safe to show in a UI.

string
createdAt
required
string format: date-time
expiresAt

When it stops working by itself — shown once, beside the token.

string format: date-time
nullable
projectId

The project the token was minted in and writes to (B8-team). Every request with it lands there, whatever X-Plune-Project says.

string
nullable
Example
{
"token": "plune_XxYy…",
"scope": "read"
}

A body that is not JSON, or a scope that is neither read nor write

Media type application/json
object
error
required
string
Example generated
{
"error": "example"
}

No / invalid session

read-only member of the project named — a reader cannot mint for it

Media type application/json
object
error
required
string
Example generated
{
"error": "example"
}

The project named is not one you are in (the same answer as an id nobody has)

Media type application/json
object
error
required
string
Example generated
{
"error": "example"
}

The account already holds the maximum of live tokens; the body names the ceiling. Not temporary — waiting changes nothing, revoking does

Media type application/json
object
error
required
string
Example
{
"error": "you already hold 10 live tokens (maximum 10) — revoke one before minting another",
"limit": 10
}

Rate-limited: the per-route throttle, or the per-minute request limit of the plan an API token counts by (#1442; the body names the plan, #2092). Retry-After carries the seconds until the window rolls over.

Media type application/json
object
error
required
string
Example generated
{
"error": "example"
}
Retry-After
integer

Seconds until the window rolls over