Skip to main content
Version: v0.25.0 (Latest)

Issue credentials

This guide covers OID4VCI issuance only. Complete these linked prerequisites before starting:

  1. Platform foundations and authentication boundaries for the tenant service token and the wallet-token boundary.
  2. Tenant provisioning and confidential-client access for the tenant and hosted authorization server.
  3. Credential designs and claims for the design, format, and claims.
  4. Status-list creation and lifecycle for any status reference; create the list before the issuer binds it.
  5. Authorization-server configuration for the AS, clients, grants, and issuer binding.
  6. Issuer configuration for the issuer identity, signing selection, and credential configuration.

For presentation requests and verification results, continue with Verifier and DCQL configuration and Trust-domain creation and verifier binding.

Full pre-authorized-code flow​

Loading example...
Loading example...

This is the smallest complete issuance run. It starts with an already configured issuer and ends with a credential plus the status reference that a verifier must evaluate.

  1. Read issuer metadata anonymously. Resolve credential_issuer, credential_endpoint, token_endpoint (or the AS metadata URL), the chosen credential_configuration_id, supported proof algorithms, and the advertised format.
  2. Create an offer with the tenant token. Select exactly one configuration and the pre-authorized_code grant. Store the returned credential_offer URI and offer/session id.
  3. Resolve the offer anonymously. The wallet fetches the URI and confirms that the offer's configuration id and grant match the issuer metadata. Do not use tenantAccessToken here.
  4. Exchange the pre-authorized code. POST to the token endpoint with the code. Store the response access_token as walletAccessToken and its expiry. The token response is not the nonce contract: do not expect or cache a generic c_nonce from it. This token belongs only to this issuance session.
  5. Resolve the issuer nonce contract. If issuer metadata advertises nonce_endpoint, POST to that exact endpoint and read the top-level c_nonce from its response. The endpoint is a single issuer capability, not a format-specific or flow-specific URL. If nonce_endpoint is absent, the issuer has not advertised a c_nonce requirement and the proof must omit the nonce claim.
  6. Build the wallet proof. Create a holder key, sign the proof JWT with the algorithm advertised by the configuration, set aud to the credential issuer, and, only when the nonce endpoint returned one, set nonce to that c_nonce. A tenant service token is not a proof of possession.
  7. Request the credential. POST the selected credential_configuration_id, requested subject claims, and proof to credential_endpoint, with Bearer walletAccessToken.
  8. Validate the response locally. Confirm the response format, issuer, configuration/type identifier, claims, validity, signature, and credentialStatus URI/index. Save the credential in the wallet only after those checks pass.
  9. Verify separately. The offer and credential response do not prove presentation. Use the verifier/DCQL guide to request a presentation, then evaluate signature, holder binding, trust, validity and current status.

The response-derived chain is:

issuer metadata -> credential_offer -> pre-authorized_code
-> walletAccessToken -> (POST nonce_endpoint -> c_nonce, when advertised)
-> credential request
-> credential + credentialStatus(status_list, status_list_index)

The canonical Postman collection follows this chain in 15 Issue SD-JWT VC and mdoc, 16 Issue W3C VC, and the later format/grant folders. The tenant token is used for offer administration; the wallet token is used only for token/credential protocol calls. Each token request stores its own response and clears incompatible stale session variables.

Postman correlation: The canonical EDK Enterprise collection keeps authorization-server setup in 09 Authorization Server Configuration, issuer setup in 10 Issuer Configuration, designs in 11 Credential Designs, standalone status publication in 12 Status Lists, issuer credential bindings in 13 Credential Configurations, and the wallet protocol in 15 Issue SD-JWT VC and mdoc (with 16 to 20 for the other grant and format profiles). In the focused folder, run 01 Create EuPid offer, 02 Resolve credential offer, 03 Fetch OID4VCI metadata, 04 Exchange pre-authorized code for token, 05 Request EuPid credential, and 06 Check EuPid offer status; the mdoc lane is 07 through 10. The wallet token is stored as walletAccessToken and is never reused for administration.

Follow the issuance path​

Treat issuance as a chain of identifiers, not as one form submission. The design supplies the credential_configuration_id; the issuer metadata publishes that configuration; the offer binds the wallet to it; the token response authorizes the credential request; and the final response contains the format-specific credential plus any status reference. Carry IDs and URIs forward from responses. Do not derive them from a display name or by incrementing an index.

The Console Test surface is useful for an operator walkthrough. The REST protocol is the integration boundary for a wallet or issuer service. The tabs below show the same material action through each surface; a Console success is not evidence that an external wallet completed the protocol.

Choose the credential format​

Use the same format from the credential design through the credential request.

CredentialOID4VCI formatType identifierStatus publication
SD-JWT VCdc+sd-jwtvctJWT Token Status List, application/statuslist+jwt
ISO mdocmso_mdocdocTypeCWT Token Status List, application/statuslist+cwt
W3C VCDM 1.1 JWTjwt_vc_jsonVCDM 1.1 context and typesBitstring Status List credential, application/vc+jwt
W3C VCDM 2.0 JWTjwt_vc_json-ldVCDM 2.0 context and typesBitstring Status List credential, application/vc+jwt

For mdoc, each requested claim includes its namespace and element name. For example, org.iso.18013.5.1/family_name is different from the JSON claim family_name.

Confirm the issuer configuration​

Issuer setup is intentionally outside this issuance guide. Follow Issuer configuration, read the issuer metadata, and confirm the selected configuration and grant are advertised before creating an offer.

Issue with a pre-authorized code​

  1. Open the issuer Test page.
  2. Select the credential configuration and a pre-authorized-code request template.
  3. Enter the claims required by the design.
  4. Create the offer and give its URI to the wallet.
  5. Open the issuance session to inspect its current state.

Issue with an authorization code​

Use this grant when the wallet must authenticate the holder or obtain consent before issuance.

Select the authorization server in the issuer settings or request template. Confirm the client, scopes, redirect URI, and claim mappings used by the credential configuration, then create the offer from the issuer Test page.

Check the issued credential​

After the credential request succeeds:

  1. Confirm that the response format matches the requested credential_configuration_id.
  2. Decode the credential with a library that supports that format.
  3. Check the issuer, type identifier, validity period, claims, and status URI and index.
  4. Store the credential in the wallet.

For mdoc, check the docType, namespace-qualified elements, DSC chain, and x5chain. For W3C credentials, check the selected VCDM context and the expected credential structure.

For SD-JWT VC, check the vct, issuer, disclosure digests, and JWT Token Status List URI/index. For ISO mdoc, check the docType, namespace-qualified elements, issuer-signed items, DSC chain, and CWT Token Status List URI/index. For W3C VCDM 1.1, check the JSON-LD context and VC/credential subject shape; for VCDM 2.0, check the VCDM 2.0 context and data-model terms. A verifier must reject an unknown format, wrong type identifier, invalid signature, expired credential, or unresolvable status URI; it must not silently reinterpret one format as another.

Next​