Registration token
Included from Basic tier
A registration token is an admin-minted, scoped fleet enrolment credential.
Runner tokens and agent tokens are one payload shape: kind scopes a
token to exactly one sort of fleet member (runner or agent; an empty
stored kind reads as runner), and agent tokens additionally carry a
project scope and an optional fixed agent code. Both kinds are served by the
same two endpoints and documented together here. (These are unrelated to the
user credentials the v2 AuthService mints — sessions and native api keys —
which are a different resource entirely.)
The v2 OpenAPI document declares this resource's schema; the resource-field coverage gate holds this page to it.
Endpoints (admin-token gated):
GET /api/registration_tokens—{"tokens": [...]}, every minted token's metadata with a derived status;?kind=runner|agentnarrows (any other value is 422). Ordered newest expiry first, fingerprint on ties. The stored token value is never returned — rows are named by the non-redeemable fingerprint, like runner keys are.POST /api/registration_tokens— mints a token; 201. The REST twin of theCreateRunnerToken/CreateAgentTokenConnect RPCs.
One-time display
The token value appears exactly once: in the create response. The listing
serves metadata only. A refused registration is deliberately an opaque
"credential invalid" to the caller (one error for unknown, expired and
exhausted alike — a bad-token holder learns nothing about which check
failed); this listing's status is where the refusal is diagnosed.
List row fields (GET /api/registration_tokens)
| Field | Type | Meaning |
|---|---|---|
fingerprint | string | sha256: + the first 16 hex characters of the value's SHA-256 — the stable display identifier. Not redeemable: registration only ever accepts the full stored value. |
kind | string | runner or agent (empty stored kind reads runner). |
group | string | The runner group the token enrols into (default default; minting auto-vivifies the group row). |
labels | string array | Labels stamped onto runners enrolled with this token. Absent when empty; always cleared on agent tokens. |
ephemeral | bool | Enrolled runners are marked ephemeral. Absent when false; always forced false on agent tokens. |
uses | int | Redemptions so far. Incremented per successful UseRegistrationToken. |
max_uses | int | Redemption cap. 0 means unlimited within the TTL; 1 is the JIT single-use shape. |
expires_at | timestamp | When the token stops redeeming. |
project | string | Agent tokens only: the normalized project path the agent is scoped to. Absent on runner tokens. |
code | string | Agent tokens only, optional: the fixed agent code the token mints. Absent when not set. |
status | string | Derived at read time — vocabulary below. |
status vocabulary
Verbatim: active, expired, exhausted. Expiry is checked first, so an
expired-and-exhausted token reads expired — the same order redemption
applies.
Create request (POST /api/registration_tokens)
| Field | Type | Meaning |
|---|---|---|
kind | string | runner (default when empty) or agent; anything else is 422. |
group | string | Target group; defaults to default. Name validated; creating a new group name is gated by the licence's runner_groups limit (422 on refusal). |
labels | string array | Labels for enrolled runners. Dropped for agent tokens. |
ttl | string | A positive Go duration (24h, 90m); default 1 hour (DefaultTokenTTL). Invalid or non-positive is 422. |
ephemeral | bool | Mark enrolled runners ephemeral. Forced false for agent tokens. |
max_uses | int | Redemption cap; 0 = unlimited within the TTL. |
project | string | Required for kind: agent ("agents are project-scoped"); normalized before storage. 422 when missing. |
code | string | Optional fixed agent code; validated when present. |
Create response (201)
| Field | Type | Meaning |
|---|---|---|
token | string | The credential itself (an ocrt_… value) — returned once, here, and never again. |
expires_at | timestamp | UTC expiry. |
fingerprint | string | The listing identifier for this token. |
kind | string | The resolved kind (runner or agent). |
group | string | The resolved group. |
Expiry and revocation
There is no revoke verb on this surface: a token stops redeeming by
expiring or exhausting its max_uses. That is also the group-deletion
contract — DELETE /api/runner_groups/{name} is refused while
still-redeemable tokens reference the group ("let them expire or exhaust
before deleting the group").
Related pages
opschain docs runner-registry— what redemption enrols and how identity works after enrolment.opschain docs entitlements— the licence gate on new group names at mint time.