Skip to main content
Version: v5.6.1

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|agent narrows (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 the CreateRunnerToken/CreateAgentToken Connect 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)​

FieldTypeMeaning
fingerprintstringsha256: + 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.
kindstringrunner or agent (empty stored kind reads runner).
groupstringThe runner group the token enrols into (default default; minting auto-vivifies the group row).
labelsstring arrayLabels stamped onto runners enrolled with this token. Absent when empty; always cleared on agent tokens.
ephemeralboolEnrolled runners are marked ephemeral. Absent when false; always forced false on agent tokens.
usesintRedemptions so far. Incremented per successful UseRegistrationToken.
max_usesintRedemption cap. 0 means unlimited within the TTL; 1 is the JIT single-use shape.
expires_attimestampWhen the token stops redeeming.
projectstringAgent tokens only: the normalized project path the agent is scoped to. Absent on runner tokens.
codestringAgent tokens only, optional: the fixed agent code the token mints. Absent when not set.
statusstringDerived 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)​

FieldTypeMeaning
kindstringrunner (default when empty) or agent; anything else is 422.
groupstringTarget group; defaults to default. Name validated; creating a new group name is gated by the licence's runner_groups limit (422 on refusal).
labelsstring arrayLabels for enrolled runners. Dropped for agent tokens.
ttlstringA positive Go duration (24h, 90m); default 1 hour (DefaultTokenTTL). Invalid or non-positive is 422.
ephemeralboolMark enrolled runners ephemeral. Forced false for agent tokens.
max_usesintRedemption cap; 0 = unlimited within the TTL.
projectstringRequired for kind: agent ("agents are project-scoped"); normalized before storage. 422 when missing.
codestringOptional fixed agent code; validated when present.

Create response (201)​

FieldTypeMeaning
tokenstringThe credential itself (an ocrt_… value) — returned once, here, and never again.
expires_attimestampUTC expiry.
fingerprintstringThe listing identifier for this token.
kindstringThe resolved kind (runner or agent).
groupstringThe 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").

  • 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.