Skip to main content
Version: Next (nightly)

API tokens

An API token is how a script, a service, or an agent authenticates to the REST API without a browser login. It is long-lived, stored hashed, and revocable, which makes it different from the short-lived session token the web app uses.

Minting one​

Create a token from the app, or over the API:

POST /api/v1/me/api-tokens

Give it a name (so you can tell your tokens apart later) and, optionally, an expiry and a set of scopes. The response includes the token's plaintext value exactly once:

{ "id": "…", "name": "backup script", "token_prefix": "cbt_AbCdEfGh",
"expires_at": null, "token": "cbt_AbCd…" }

The full value starts with cbt_. Cobblr keeps only a SHA-256 hash of it, so it can never show you the value again. If you lose it, revoke it and mint a new one. The token_prefix is stored for display, so the token list can show you which one is which without holding the secret.

List your tokens (hashes only, never the plaintext) with GET /api/v1/me/api-tokens. Each row carries last_used_at, expires_at, and revoked_at so you can see what is live and what has lapsed.

Expiry and revocation​

Leave expires_at unset and the token never expires. Set it to an ISO timestamp and the token stops working after it. Either way you can revoke a token at any time, which invalidates it immediately: an authenticated request with a revoked or expired token is rejected the same as a bad one.

Rotating a token​

A token's scopes can never be edited. Its value is already sitting in some daemon's environment, so changing what it reaches would change the reach of a credential someone already holds, and the record of what that token could do would stop being true. Rotate instead.

  1. Press the rotate button on the token's row. The mint dialog reopens prefilled with that token's name and scopes.
  2. Adjust either, then mint. The new value is shown once.
  3. Paste it wherever the old one is used, then revoke the old one. The reveal screen offers that revoke directly.
  • The old token stays live until you revoke it, so the daemon using it does not go down mid-swap.

What a token can do​

A token acts as the user who created it, so its baseline reach is that person's role in each workspace. There are two modes:

  • Unscoped (no scopes given). The token can do anything its owner can do, across the workspaces they belong to. Use this for a trusted script you run yourself, and treat it like a password.
  • Scoped. Attach one or more scopes and the token becomes deny-by-default: it is clamped to the routes those scopes allow and nothing else, even though it still carries the owner's identity. A token scoped to one job can only do that job.

Scopes are a fixed, curated set, each mapping to a narrow list of routes, rather than a general read/write-per-area permission builder. Fetch the current choices with GET /api/v1/me/api-token-scopes. The two most relevant to a self-hoster:

  • devices:edge: lets an on-site edge bridge register, poll, respond, and self-update for one workspace. Safe to hand to a bridge running on a Pi or a mini-PC, because it can reach nothing else.
  • drive:control: lets an agent drive your own open browser tab (open pages, point, follow along) and reads or writes no workspace data. It is gated further by a per-workspace opt-in that is off by default. See Connecting Claude.

The remaining scopes exist for first-party operational tooling (feedback intake, release announcements, and the like) and are narrow by design.

Handling tokens safely​

Never put a token literally on a command line or in a committed file. Read it from an environment variable or a file with tight permissions, and prefer a scoped token whenever the job is narrow enough to name.