For the complete documentation index, see llms.txt. This page is also available as Markdown.

Issuance Sessions

Every credential offer created by an issuer opens an issuance session that the platform tracks from the moment the offer is generated until the credential is delivered to a wallet (or the offer expires). Issuance sessions let you observe issuance progress, retrieve the offer URI again, and regenerate the QR code — without re-creating the offer.

All issuance-session endpoints require a valid Bearer token:

Authorization: Bearer <token>

The service validates the JWT against the configured JWKS endpoint; any valid token is accepted at this layer (see Authentication).

How a session is created

A session is opened automatically when you create a credential offer — there is no separate create-session endpoint. The offer response returns an issuanceSessionId, which is the handle for every operation on this page.

POST /issuers/:issuerDid/credential-offers

POST /issuers/did:key:z6Mkk.../credential-offers
Authorization: Bearer <token>
Content-Type: application/json

Request Body

{
  "credentialConfigurationIds": ["[email protected]:sd-jwt"],
  "requirePin": false,
  "issuanceMetadata": {
    "claimsByConfigurationId": {
      "[email protected]:sd-jwt": {
        "employee_id": "EMP-001",
        "full_name": "Ada Lovelace",
        "department": "Engineering"
      }
    }
  }
}

Response Body

  • credentialOfferUri: The openid-credential-offer:// URI a wallet scans or follows to claim the credential.

  • issuanceSessionId: The identifier of the session opened for this offer. Use it to track progress and to fetch the session's QR code.

  • credentialConfigurationIds: The credential configuration ids the offer covers, each of the form Name@Version:format.

  • userPin: Present only when requirePin is true; the PIN the holder must enter to complete the pre-authorized code flow.

Optional fields such as userPin are omitted from the JSON when they do not apply (for example, when requirePin is false) rather than returned as null. Keep the returned issuanceSessionId — it is the path parameter for the get-session and QR-code endpoints below.

List sessions for an issuer

Returns all issuance sessions belonging to a single issuer DID, most useful for an operator dashboard that shows pending and completed offers. The issuerId query parameter filters sessions to one issuer; it is not checked against existing issuers, and omitting it returns all issuance sessions across all issuers.

GET /issuance-sessions?issuerId=<issuerId>

Response Body

  • issuerId: The issuer DID to filter by, passed as the issuerId query parameter.

For a freshly created OfferCreated session, issuedCredentials is an empty array (no credentials have been issued yet), and the optional userPin and errorMessage fields are absent from the JSON because they do not apply.

Get a single session

Reads one session by its identifier, returning its current state and all tracking fields.

GET /issuance-sessions/:sessionId

Response Body

Optional fields are omitted when they do not apply: userPin appears only when the offer required a PIN, and errorMessage appears only when the session ended in the Error state.

Session fields

  • id: Internal session identifier (the same value as issuanceSessionId from the offer response).

  • issuerId: The issuer DID that owns the session.

  • state: Current lifecycle state of the session (see below).

  • credentialOfferUri: The credential offer URI tied to the session.

  • createdAt: ISO 8601 timestamp of when the session (and offer) was created.

  • expiresAt: ISO 8601 timestamp after which the offer can no longer be claimed.

  • userPin: The PIN for the pre-authorized code flow, present only when the offer required one.

  • errorMessage: A human-readable error message when the session ended in the Error state; otherwise absent.

  • issuedCredentials: The credential configuration ids issued in this session (for example [email protected]:sd-jwt). It is an empty array until issuance completes, and is filled in as credentials are issued (fully populated once the state reaches Completed).

Session states

The state field advances through the OpenID4VCI pre-authorized code flow as the wallet interacts with the issuer:

  • OfferCreated: The offer has been generated and the session is waiting for a wallet to retrieve it.

  • OfferUriRetrieved: A wallet has fetched the offer payload from the offer URI.

  • AuthorizationInitiated / AuthorizationGranted: Authorization steps preceding token issuance.

  • AccessTokenRequested / AccessTokenCreated: The wallet has requested and received an access token to call the credential endpoint.

  • CredentialRequestReceived: The wallet has submitted a credential request.

  • CredentialsPartiallyIssued: At least one — but not all — of the offered credentials has been issued.

  • Completed: All offered credentials have been issued; issuedCredentials lists their configuration ids.

  • Error: Issuance failed; errorMessage describes what went wrong.

To track issuance progress, poll GET /issuance-sessions/:sessionId and watch the state field. A session is finished when it reaches Completed (success) or Error (failure), or when expiresAt has passed without completion.

Get the session QR code

Returns a PNG QR code that encodes the session's credential offer URI. This is handy for re-displaying an offer for an existing session without creating a new one — for example, refreshing the QR shown in an operator panel.

GET /issuance-sessions/:sessionId/qr-code

Response

  • Body: A 400×400 PNG image (Content-Type: image/png) of the QR code.

  • Header X-Credential-Offer-Uri: The openid-credential-offer:// URI encoded in the QR code, so callers can copy the offer without decoding the image.

A wallet that scans this QR code is taken through the same flow as the original offer, and its progress is reflected in the same session. The endpoint always regenerates the image from the session's stored offer URI, so it stays valid for the life of the offer (until expiresAt).

Issuance session QR code in the operator console
An issuance session and its QR code in the operator console (Issuance Sessions tab)

Notes

  • Use the issuanceSessionId from the offer response as the :sessionId path parameter for the get-session and QR-code endpoints.

  • If you need the offer URI and QR at creation time rather than after the fact, the credential-offer endpoint has a qr-code variant (POST /issuers/:issuerDid/credential-offers/qr-code) that returns the PNG directly with X-Credential-Offer-Uri, X-Issuance-Session-Id, and X-Pin headers. See the credential issuance flow documentation.

Last updated