OpenID4VCI Protocol

Token endpoint (pre-authorized_code grant)

OpenID4VCI token endpoint. Implements the pre-authorized_code grant only: the wallet exchanges the pre-authorized_code from a credential offer (and the transaction code if the offer required one) for a short-lived Bearer access token used at the credential endpoint. Public and unauthenticated (the pre-authorized_code itself is the capability). The token is single-use and expires in 300 seconds. tx_code is brute-force protected — after 5 failed attempts the offer locks out. The grant fails (HTTP 400 invalid_grant) if the code is unknown, already redeemed, expired, or the tx_code is wrong; an unsupported grant_type returns 400 unsupported_grant_type.

post/v1/oauth/token

Request body

grant_typestring required

OAuth grant type. Must be exactly urn:ietf:params:oauth:grant-type:pre-authorized_code — the only grant the token endpoint supports. Any other value returns 400 unsupported_grant_type.

pre-authorized_codestring required

The pre-authorized code issued with the credential offer (the pre_authorized_code field of POST /v1/credential-offers, also present in the offer's grants object). The endpoint also accepts the snake_case alias pre_authorized_code. Identifies the offer being redeemed.

tx_codestring

The transaction code (PIN) for offers created with tx_code: true. A 6-digit numeric string communicated to the holder out-of-band. Omit (or send empty) for offers that have no tx_code. After 5 wrong attempts the offer is locked.

Example request

{
  "grant_type": "urn:ietf:params:oauth:grant-type:pre-authorized_code",
  "pre-authorized_code": "s8Ilre7v2K9pQx1bN4mZ",
  "tx_code": "517082"
}

Response

Access token issued.

access_tokenstring

Opaque Bearer access token. Send it as Authorization: Bearer <access_token> to POST /v1/credential. Single-use and valid for expires_in seconds.

token_typestring

Token type. Always the literal bearer.

expires_ininteger

Access token lifetime in seconds. Always 300 (5 minutes).

Example response

{
  "access_token": "5a0W4gQ2tR8yU1vC7pLxZ3mB6nK9dF0",
  "token_type": "bearer",
  "expires_in": 300
}

Changes