Token API
POST /v1/token/exchange
RFC 8693 token exchange — form-encoded, not JSON, and its errors follow RFC 6749 §5.2
({"error": "...", "error_description": "..."}) rather than this project's usual error
envelope, since an OAuth client already knows how to read that shape.
Request (application/x-www-form-urlencoded):
| Field | Required | Notes |
|---|---|---|
grant_type | Yes | Must be urn:ietf:params:oauth:grant-type:token-exchange |
subject_token | Yes | The presented (current-hop) token |
subject_token_type | Yes | Must be urn:ietf:params:oauth:token-type:jwt |
resource | Yes | The target this exchange narrows to |
scope | Yes | The data class this exchange narrows to |
action_id | Yes | The action_id from the POST /v1/authorize allow this exchange spends |
actor_token / actor_token_type | No | Proof-of-possession actor assertion (future identity work) |
audience | No | |
taint | No |
An exchange re-decides rather than trusting that /v1/authorize was called first, and it
only succeeds if action_id names a committed allow row matching this exact hop
(session, caller, target, data class) — see
The delegation-chain audit model.
Response — 200:
{"access_token": "<JWT, hop N+1>", "issued_token_type": "urn:ietf:params:oauth:token-type:jwt", "token_type": "Bearer", "expires_in": 60}
Decoded, the new token's sub is unchanged, aud is exactly resource, scope is exactly the
requested scope, hop is one greater than the subject token's, and act nests the subject
token's own sub — the delegation proof.
Errors (RFC 6749 shape, all in the error/error_description form above):
| HTTP | error | Meaning |
|---|---|---|
403 | invalid_target | The recorded allow no longer holds under a fresh decision |
400 | invalid_grant (already exchanged) | subject_token's jti was already spent |
400 | invalid_grant (bad action_id) | Missing or malformed action_id |
503 | invalid_grant (guard unavailable) | Single-use replay guard couldn't be reached; refuses to issue rather than risk a double-mint |
See JWKS for the companion endpoint a resource server uses to verify the tokens this endpoint mints, offline.