Authorization
The id-token registry: which tokens an environment authorizes, and their lifecycle. Admin manages the registry; recovering a token's *value* takes Owner and is audited — see docs/adr/0007-the-authorization-registry-stores-recoverable-token-values.md. No listing endpoint ever returns a token value.
8 endpoints
Lists an environment's authorized tokens, paginated. Pass `q` to filter by label.
get/v1/environments/{environment_id}/id-tokensRequires a bearer token
Never returns a token's value — see
[crate::id_tokens::reveal::reveal_id_token] for that.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| environment_id* | path | string<uuid> | Environment id |
| page | query | integer<int32> | 1-indexed page number. Defaults to 1. |
| per_page | query | integer<int32> | Tokens per page, capped at 100. Defaults to 20. |
| q | query | string | Free-text filter over label, matched case-insensitively as a
substring. Does not match token values — they are not searchable
by construction, since the stored hash is a keyed digest and
indexing plaintext would defeat encrypting it. |
Responses
| Status | Body | Description |
|---|---|---|
| 200 | ListIdTokensResponse | A page of the environment's authorized tokens |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 403 | ErrorBody | The caller is a member but below Admin |
| 404 | ErrorBody | No environment with this id exists, or the caller cannot access it |
Enrols a token in an environment.
post/v1/environments/{environment_id}/id-tokensRequires a bearer token
The value is hashed and encrypted in a single write, so the row is both recognisable on the authorize path and recoverable for the features that must put it back on the wire. The response does not echo the value.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| environment_id* | path | string<uuid> | Environment id |
Request bodyCreateIdTokenRequest
| Field | Type | Description |
|---|---|---|
| expires_at | string | null<date-time> | — |
| label | string | null | — |
| token_type | string | null | Free text — see [IdTokenView::token_type]. |
| value* | string | The token value, e.g. an RFID UID. Stored hashed (for authorization) and encrypted (so it can be pushed to a charging_station later) in one write. |
Responses
| Status | Body | Description |
|---|---|---|
| 201 | IdTokenView | The token is enrolled |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 403 | ErrorBody | The caller is a member but below Admin |
| 404 | ErrorBody | No environment with this id exists, or the caller cannot access it |
| 409 | ErrorBody | This token is already enrolled in this environment |
Fetches one registry entry. Carries no token value.
get/v1/id-tokens/{id}Requires a bearer token
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | string<uuid> | Id token id |
Responses
| Status | Body | Description |
|---|---|---|
| 200 | IdTokenView | The registry entry |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 403 | ErrorBody | The caller is a member but below Admin |
| 404 | ErrorBody | No id token with this id exists, or the caller cannot access its environment |
Removes a token entirely, cascading to its reveal audit history.
delete/v1/id-tokens/{id}Requires a bearer token
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | string<uuid> | Id token id |
Responses
| Status | Body | Description |
|---|---|---|
| 204 | — | The token is removed |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 403 | ErrorBody | The caller is a member but below Admin |
| 404 | ErrorBody | No id token with this id exists, or the caller cannot access its environment |
Permanently destroys a token's hash and stored value. **`Owner` only** — at least as privileged as [`crate::id_tokens::reveal::reveal_id_token`] (C-16): erasure is irreversible where reveal is not.
post/v1/id-tokens/{id}/eraseRequires a bearer token
Idempotent (C-18): erasing an already-erased token still answers 200
and still records a new attempt — the attempt, not the state change, is
the auditable event, the same rule [crate::id_tokens::reveal::reveal_id_token]
already applies to a token with no stored value.
The response carries no token value and no fragment of one (C-21).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | string<uuid> | Id token id |
Responses
| Status | Body | Description |
|---|---|---|
| 200 | EraseResponse | The token's hash and stored value are destroyed |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 403 | ErrorBody | The caller may manage this environment but is not an Owner |
| 404 | ErrorBody | No id token with this id exists, or the caller cannot access its environment |
Recovers a token's plaintext value. **`Owner` only.**
post/v1/id-tokens/{id}/revealRequires a bearer token
Answers 200 with "value": null and a reason for a token enrolled
before value storage existed — a successful answer to a well-formed
question about a token that exists. A 404 would be wrong (the token is
there) and a 500 would be wrong (nothing failed), and neither would let a
client offer the re-enrolment that actually fixes it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | string<uuid> | Id token id |
Responses
| Status | Body | Description |
|---|---|---|
| 200 | RevealResponse | The token's value, or an explanation of why it is unrecoverable |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 403 | ErrorBody | The caller may manage this environment but is not an Owner |
| 404 | ErrorBody | No id token with this id exists, or the caller cannot access its environment |
Who has read this token's value, and when. **`Owner` only** — the list of who accessed a credential is itself sensitive.
get/v1/id-tokens/{id}/revealsRequires a bearer token
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | string<uuid> | Id token id |
| page | query | integer<int32> | — |
| per_page | query | integer<int32> | — |
Responses
| Status | Body | Description |
|---|---|---|
| 200 | ListRevealsResponse | A page of this token's reveal history |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 403 | ErrorBody | The caller may manage this environment but is not an Owner |
| 404 | ErrorBody | No id token with this id exists, or the caller cannot access its environment |
Blocks a token. Takes effect on the next `Authorize` — the gateway already honours `blocked_at`, so nothing there changes.
post/v1/id-tokens/{id}/revokeRequires a bearer token
Distinct from DELETE, which removes the row and its reveal history:
revoking keeps both.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
| id* | path | string<uuid> | Id token id |
Responses
| Status | Body | Description |
|---|---|---|
| 200 | IdTokenView | The token is blocked |
| 401 | ErrorBody | Missing, invalid, or expired bearer token |
| 403 | ErrorBody | The caller is a member but below Admin |
| 404 | ErrorBody | No id token with this id exists, or the caller cannot access its environment |