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

Credential status profile walkthroughs

Every walkthrough follows the same boundary: issuer setup and design, status-list setup, offer creation, wallet token exchange, format-specific credential request, response-derived status identifiers, wallet storage/presentation, verifier checks, and a status transition. An offer is only the backend issuance entry point. It does not establish token exchange, credential issuance, wallet storage, presentation, or verifier trust.

Direct Developer Console workflow​

Use the tenant's Developer Console for backend REST operations: configure designs and credential configurations, create and read status lists, create an issuance offer, and track its session. Wallet grant exchange, credential retrieval, storage, and presentation are separate holder activities, not Developer Console requests. The existing protocol captures below remain illustrations of that boundary, not captures of the new console transport.

For each profile below, select createCredentialOffer in oid4vci-issuer-session-openapi.yml: POST /api/oid4vci/v1/backend/credential/offers. Supply credential_configuration_ids from the configured issuer, and issuer_id when the issuer cannot be resolved from context. The minimal JSON examples below show request shape, not newly captured executions; add subject data and grant options required by your configuration. Do not send a testing-action envelope or assume that a credential design name is an issuer configuration ID.

Retain the returned correlation_id, offer_uri, and status_uri. Hand offer_uri to a separate wallet, then use getCredentialOfferStatus with the returned correlation ID. Only credential_issued reports completed issuance; issuance_data contains configuration and credential identifiers, not a substitute for reading the credential-bound status URI/index.

Loading example...

For status administration, retain the list ID from createStatusList; use getStatusListEntry and updateCredentialStatus with the issued credential's actual entry index. List creation does not allocate an entry. Preserve the media type and binary bytes for CWT status responses.

Loading example...
Loading example...

For verification, configure the verifier, DCQL binding, and trust policy first. Use create-authorization-request in oid4vp-universal-openapi.yml, pass the returned request URI to a separate holder, and use get-authorization-status for backend progress and results. A newly created request or pending status is not a successful verification. See Verify credentials for the captured request/status sequence.

Loading example...
Loading example...

1. SD-JWT VC + JWT Token Status​

Profile. Use an SD-JWT VC design bound to dc+sd-jwt and a vct. Publish an IETF JWT Token Status List with application/statuslist+jwt; the status URI and index belong to the issued credential.

Setup and design. Create the credential design and the standalone status list as separate resources. At status-list creation, a tenant operator may select any existing, usable key that the platform has authorized for status-list signing; the status-list name is only the list's correlation identifier and never creates, derives, or selects a key. In normal issuer deployments, select the same resource, key alias, and DID assertion method (or certificate identity) that the issuer uses to sign the credential, so verifiers see one consistent signer identity. Retain the status-list response id and public statusListUri, then configure the issuer credential with the list's correlationId as status.statusListId and the same signing selection. Do not call a signing-key endpoint containing a future status-list name before the list exists. The issued credential response later supplies the credential-bound status URI and index; list creation does not allocate an index for a credential that does not yet exist. An Azure KMS/BYOK/BYOC setup can protect the signing key, but key custody is not issuer trust.

Offer, token, and request. Create the backend offer with the advertised SD-JWT configuration (the example uses EuPid). The separate wallet resolves the offer, discovers the advertised token and credential endpoints, exchanges the grant for an access token, and sends a credential request with the requested configuration and an OID4VCI proof. The credential response must be decoded as SD-JWT VC and checked for issuer, vct, claims, validity, and the embedded status URI/index.

Loading example...
{"credential_configuration_ids": ["EuPid"]}

This existing issuance call is an unmatched protocol-shape illustration (capture.unmatched: true), not a live execution of all four profiles. Its URL is not mapped to a CapturedCall API-reference target. The source-backed ApiOperation above describes backend offer creation, not this wallet credential request.

Request EuPid credential

Endpoint: POST /oid4vci/cap0924b/oid4vci/credential

Captured response: 200 OK

This captured endpoint is shown from the E2E run; it is not mapped to one of the generated EDK REST API reference pages.

Live against connected environment

Connect an environment to rewrite this call to real service bases and run it.

Wallet and presentation boundary. Store the returned SD-JWT VC in the wallet only after local checks. A successful credential response is not an OID4VP presentation. The holder must later select disclosures, produce a presentation, and let the verifier apply its DCQL and trust policy.

Status transition and failure meaning. The issuer changes the response-derived index through status-list management, then publishes a fresh signed JWT. A verifier refreshes the URI, validates the JWT and its TTL, reads the index, and rejects a revoked or unavailable entry. A stale cache, wrong URI, wrong index, invalid signature or malformed token fails the check. A successful offer does not prove that the credential is valid.

Fetch hosted status list token

Endpoint: GET /public/statuslists/eupid-revocation

Captured response: 200 OK

This captured endpoint is shown from the E2E run; it is not mapped to one of the generated EDK REST API reference pages.

Live against connected environment

Connect an environment to rewrite this call to real service bases and run it.

Open Issuer → Credentials/Test and confirm the selected design, credential_configuration_id, dc+sd-jwt, vct, status-list URI, and returned status index before presenting. The existing design illustration shows where shared design fields are reviewed; it is not a live SD-JWT run.

Credential design fields used by the SD-JWT profile

2. ISO mdoc + CWT Token Status​

Profile. Use an ISO/IEC 18013-5 mdoc design bound to mso_mdoc and a docType. Publish an IETF CWT Token Status List with application/statuslist+cwt. The status response is raw COSE/CBOR, not JSON.

Setup and design. Define namespace-qualified elements, choose the mdoc signing material, and create the one-bit CWT status profile. Retain the status-list response's correlationId and public URI; the issued mdoc response later supplies the credential-bound status URI and index. Establish the DSC chain to an IACA and configure the verifier's trust domain. If a signed VICAL is part of the policy, admit its signer and its issuing-authority entries separately; VICAL is not a status list and Azure key storage does not establish either trust decision.

Offer, token, and request. Create the backend offer with the advertised mdoc configuration (the example uses Mdl). The separate wallet resolves the offer and obtains a token, then submits an mdoc-aware credential request with the required proof and namespaced claims. Check the response's docType, namespaces, issuer-signed MSO, x5chain, and status URI/index. Preserve binary COSE/CBOR bytes and their media type at every status boundary.

Loading example...
{"credential_configuration_ids": ["Mdl"]}

This existing mdoc call is an unmatched protocol-shape illustration (capture.unmatched: true). Its response is application/json with credential: "<base64 payload omitted>"; it does not show decoded docType, namespaces, MSO, x5chain or status URI/index, and it has no API-reference mapping. Use the separate source-backed ApiOperation surfaces for the contract.

Request Mdl credential

Endpoint: POST /oid4vci/cap0924b/oid4vci/credential

Captured response: 200 OK

This captured endpoint is shown from the E2E run; it is not mapped to one of the generated EDK REST API reference pages.

Live against connected environment

Connect an environment to rewrite this call to real service bases and run it.

Wallet and presentation boundary. Storing the mdoc is a wallet operation. A later device response proves a presentation exchange only when the holder device, reader request, issuer signature, device signature, and verifier policy all succeed. The credential request capture above does not prove that device flow.

Status transition and failure meaning. After a response-derived index is changed, the verifier fetches application/statuslist+cwt, decodes COSE/CBOR, validates the CWT issuer, expiry, signature and one-bit value, and compares the index from the mdoc. Missing binary data, a JSON response where COSE is required, an untrusted DSC/IACA/VICAL chain or a revoked bit fails the check. See mDoc VICAL and CWT status for configuration and generic trust-source activation.

Loading example...

In Issuer → Credentials/Test, confirm mso_mdoc, docType, namespace-qualified elements, and the response-derived status URI/index. In Trust domains, open the domain and use its Anchors section to inspect the DSC/IACA anchors. Admission classes and VICAL configuration are not shown in the console; read them through the Trust Domain API. The shared trust screenshot is configuration guidance only.

Trust domain fields used by the mdoc profile

3. W3C VCDM 1.1 JWT + Bitstring Status List​

Profile. Create a W3C VCDM 1.1 design with its context and types, bind jwt_vc_json, and publish a Bitstring Status List credential as application/vc+jwt. The VCDM version, context, and status representation must remain consistent from design through verification.

Setup and design. Create and resolve the design, choose the issuer DID/JWK or X.509 key, create the Bitstring list with spec: bitstring_status_list, one bit per status, and revocation purpose, then bind its correlationId as status.statusListId. The list response supplies the correlationId and public URI. The issued VC-JWT response later supplies the credential-bound status URI and index; do not guess either from a label.

Offer, token, and request. The source-backed design example binds EmployeeCredentialV11, while the canonical offer example selects Vcdm11Jwt; these are distinct example identities, not interchangeable IDs. Before creating an offer, the issuer must already be configured and must advertise credential_configurations_supported[Vcdm11Jwt] in issuer metadata. The offer request selects the advertised value through plural credential_configuration_ids: [Vcdm11Jwt], and the resolved offer repeats credential_configuration_ids: [Vcdm11Jwt]. Only after token exchange does the token response expose singular authorization_details[].credential_configuration_id; check it then against the canonical ID. The design POST alone does not create this issuer configuration. The wallet then follows issuer metadata, exchanges the grant, and submits its proof and jwt_vc_json credential request. The returned VC-JWT must use the VCDM 1.1 context and types and carry a response-derived Bitstring status URI/index. It is not interchangeable with the VCDM 2.0 profile.

Loading example...
{"credential_configuration_ids": ["Vcdm11Jwt"]}
Loading example...

Wallet, presentation, and verification. Wallet storage does not prove an OID4VP presentation. A verifier checks the JWT signature, issuer trust-domain attachment, VCDM 1.1 context/types, validity, DCQL result, and the signed Bitstring Status List at the credential's URI/index. A status entry that cannot be fetched or decoded is not an implicit valid result.

Status transition and failure meaning. Update the response-derived index, publish the new signed list, and refresh it after its cache policy permits. A revoked bit, wrong list specification, wrong index, stale or unverifiable VC-JWT, missing trust attachment or VCDM 1.1/2.0 mismatch fails the check. There is no fallback to another credential profile.

Loading example...

In Issuer → Credentials/Test, confirm the VCDM 1.1 context/types, jwt_vc_json, canonical Vcdm11Jwt configuration, Bitstring purpose, list media type, URI, and returned index. The design name and the offer configuration are different fields and must not be conflated.

Bitstring status-list fields used by the VCDM 1.1 profile

4. W3C VCDM 2.0 JWT-JSON-LD + Bitstring Status List​

Profile. Create a W3C VCDM 2.0 design with the VCDM 2.0 context and types, bind jwt_vc_json-ld, and publish a Bitstring Status List credential as application/vc+jwt. This profile has the same status mechanism as VCDM 1.1 but a different credential model and securing-format identifier.

Setup and design. Resolve the VCDM 2.0 design, choose signing material and trust-domain policy, create the one-bit Bitstring list, and retain the list response's ID and public URI. The issued VC-JWT-JSON-LD response later supplies the credential-bound status URI and index. The source-backed design example binds EmployeeCredentialV20, while the canonical offer example selects Vcdm20JwtLd; these are distinct example identities, not interchangeable IDs. Before creating an offer, the issuer must already be configured and must advertise credential_configurations_supported[Vcdm20JwtLd] in issuer metadata. The offer request selects the advertised value through plural credential_configuration_ids: [Vcdm20JwtLd], and the resolved offer repeats credential_configuration_ids: [Vcdm20JwtLd]. Only after token exchange does the token response expose singular authorization_details[].credential_configuration_id; check it then against the canonical ID. The design POST alone does not create this issuer configuration; do not reuse the VCDM 1.1 configuration or context.

Offer, token, and request. Use createCredentialOffer with the advertised Vcdm20JwtLd configuration. The separate wallet resolves the offer, exchanges the advertised grant, and submits a proof-bearing jwt_vc_json-ld request. Inspect the returned credential, context, types, issuer, validity, and Bitstring status URI/index before wallet storage.

Loading example...
{"credential_configuration_ids": ["Vcdm20JwtLd"]}
Loading example...

Wallet, presentation, and verification. A stored JWT-JSON-LD credential is not proof of presentation or trust. During OID4VP, the verifier evaluates the requested claims, JWT signature, VCDM 2.0 context/types, issuer trust, validity, and current Bitstring status. The verifier must not silently downgrade it to the VCDM 1.1 interpretation.

Status transition and failure meaning. Change the index using status management, republish the signed Bitstring credential, and refresh it according to its cache policy. Reject a revoked or undecodable entry, an invalid proof, a mismatched VCDM context, a missing trust attachment or an unavailable status URI. This prevents missing status or trust input from being accepted.

Loading example...

In Issuer → Credentials/Test, confirm the VCDM 2.0 context/types, jwt_vc_json-ld, canonical Vcdm20JwtLd configuration, Bitstring purpose, list media type, URI, and returned index. Do not reuse the VCDM 1.1 configuration or context.

Bitstring status-list fields used by the VCDM 2.0 profile

Request, response, and API-reference surfaces​

The API components above are source-backed OpenAPI operations and examples; they describe request schemas, response fields, and named examples, not a live execution. Existing matched CapturedCall components add Overview, Request, Response, and API-reference tabs for selected sanitized calls. The two unmatched issuance illustrations above do not have an API-reference mapping; use the separate ApiOperation surfaces for that contract. Read the request and response together: list creation returns the list ID and public URI, while issuance returns the credential-bound status URI and index.

Use Issue credentials for the issuer and wallet boundary, Verify credentials for DCQL and OID4VP, Status lists and revocation for transitions, and Trust domains for attachments and admissions. For direct execution, Developer Console explains catalog filtering, Scalar/OpenAPI, same-origin gateway requests with login/STS authorization, and Postman handoff. Browser, wallet/device, verifier, Azure, and VICAL runtime acceptance require separate proof.

Revoke a status entry

Endpoint: POST /api/statuslist/v1/statuslists/00000000-0000-4000-8000-000000000000/status

Captured response: 200 OK

This captured endpoint is shown from the E2E run; it is not mapped to one of the generated EDK REST API reference pages.

Live against connected environment

Connect an environment to rewrite this call to real service bases and run it.