oid4vcis2s November 2026
Oliver Standards Track [Page]
Workgroup:
OpenID Digital Credentials Protocols
Published:
Author:
G. Oliver
Google

OpenID for Verifiable Credential Issuance: Server to Server - Editor's draft

Abstract

This specification defines an API for the issuance and management of Verifiable Digital Credentials between a Wallet Server and Issuer Server, while keeping sensitive user data confidential between a Wallet Client Instance and the Issuer (i.e., not revealing it to the Wallet Server).

▲

Table of Contents

1. Introduction

This specification defines a set of APIs and a protocol for credential issuance and lifecycle management. It is credential format agnostic so Credentials can be of any format. Credentials can be of any format including, but not limited to, IETF SD-JWT VC [I-D.ietf-oauth-sd-jwt-vc], ISO mdoc [ISO.18013-5], and W3C VCDM [VC_DATA_2.0].

It is intended to be used to allow a Wallet to provide server infrastructure to facilitate improved reliability and security of credential issuance and lifecycle management, while adhering to principles of data minimization and user privacy.

The communication between the Wallet Server and the Wallet Client is out of scope of this specification.

2. Requirements Notation and Conventions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

3. Terminology

This specification uses the terms "Credential", "Credential Configuration", "Credential Dataset", "Credential Format", "Holder", "Presentation", "Verifiable Credential" and "Verifiable Presentation" as defined in OpenID4VCI.

This specification defines the following terms. In the case where a term has a definition that differs, the definition below is authoritative for this specification.

Credential Id:
An identifier for a Credential Dataset that an Issuer has issued, or can issue, to a particular Wallet Client Instance. Each Credential Id corresponds to a single Credential Configuration and has a 1:1 relationship with a credential status. A Credential Id can cover a batch of Credentials, in which case the status of individual Credentials within the batch cannot be changed independently.
Credential Issuer (or Issuer):
An entity that issues Verifiable Credentials. In the context of this specification, the Credential Issuer implements the Issuer Endpoints.
Issuer Server:
The server component used by an Issuer to implement the Issuer Endpoints as defined in this specification. It performs the verification, issuance and lifecycle management of credentials.
Verifiable Digital Credential (VDC):
Synonymous with Credential or Verifiable Credential.
Verification:
Verification in this specification refers to the process by which an Issuer determines that a Wallet Client Instance is authorized to have particular Credentials issued to it.
Verification Id:
An identifier generated by the Issuer for a particular verification session. Must be unique for a given Wallet Id.
Wallet:
An entity used by the Holder to request, receive, store, present, and manage Verifiable Digital Credentials and cryptographic key material. In the context of this specification it is split into two components: the Wallet Client and a Wallet Server.
Wallet Client:
A client application, that is under the control of the Holder, that Credentials will be installed on.
Wallet Client Instance:
A specific instance of a Wallet Client.
Wallet Encryption Key (WEK):
A key type provided by a Wallet Client Instance for the Issuer to encrypt sensitive data to.
Wallet Id:
A unique identifier, generated by a Wallet on initiating Verification with an Issuer. It persists across all subsequent interactions, identifying that Wallet Client Instance to that Issuer. A new initiation between the same Wallet and Issuer can result in a different Wallet Id.
Wallet Provider:
The entity who provides the technical solutions for the Wallet Client and the Wallet Server.
Wallet Server:
A server component that provides infrastructure to facilitate improved reliability and security of credential issuance and lifecycle management. In the context of this specification it is responsible for implementing the Wallet Server Endpoints, and communicating with the Wallet Client.
Wallet Signing Key (WSK):
An asymmetric key pair generated by a Wallet Client Instance used as a proof-of-origin for payload generated on the client for the Issuer.

4. Overview

This specification defines endpoints on both the Wallet Server and Credential Issuer Server to perform credential issuance and lifecycle management. This specification is designed for use with an architecture involving 3 components:

      +-------------------------------------------+
      |                  Wallet                   |
      |                                           |            +---------------+
      |  +-------------+         +-------------+  |            |     Issuer    |
      |  |             |         |             |  |            |               |
      |  |   Wallet    |         |   Wallet    |  |            | +-----------+ |
      |  |   Client    |<------->|   Server    |<--------------->|  Issuer   | |
      |  |             |  Out of |             |  | OpenID4VCI | |  Server   | |
      |  +-------------+  Scope  +-------------+  |  S2S API   | +-----------+ |
      |                                           |            |               |
      +-------------------------------------------+            +---------------+

{: #architecture-diagram title="Architecture Overview"}

The goal of this protocol is to enable a Wallet Server to improve the reliability, security and management of Credentials issued to the Holder while using application-layer encryption and wallet client authentication to minimize the sensitive user data unnecessarily exposed to the Wallet Server. Due to their distributed nature, Client applications are notoriously difficult to update, have poor connectivity, slower analytics and are a less trusted environment. An Issuer Server could work around these issues, but as the provider of both the Client and the Server, the Wallet Provider can be in a better position to alleviate these problems.

At a high level the protocol works as follows:

In advance of any communication, the Wallet Server and Issuer Server authenticate via mTLS, which is used at all endpoints. The Wallet Server is responsible for authenticating the Wallet Client and ensuring it is in a good state before communicating with the Issuer Server.

Issuance begins with a Verification phase. This phase serves two purposes:

This is done as follows:

  1. The Wallet Client Instance generates a WSK, and the Wallet Server initiates the Verification on the Issuer Server.

    1. The Wallet provides Credential Configuration(s) to identify the type of credentials they wish issued.
    2. The Wallet provides a stable unique Wallet Id associated with the WSK and the Issuer provides a stable Verification Id to reference this session.
  2. The Wallet Client Instance collects Verification Data and signs-then-encrypts it using the WSK and the Issuer Encryption Key.

    1. Examples include digital credential presentations, auth on web, wallet collected documents and liveness/selfie checks.
  3. The Wallet Server calls The Issuer Server, passing Wallet Client-supplied Verification Data and, optionally, providing additional Wallet Server-supplied Verification Data.

    1. As an optimization, Verification Data can be provided in the initial call.
    2. Examples include risk and fraud signals or server collected verification data and evaluations.
  4. The Issuer Server decrypts and verifies the Verification Data using the WSK, and evaluates it along with any Wallet Server provided Verification Data.

    1. The Issuer can perform the evaluation asynchronously to support evaluations that are not immediate (such as human reviews).
    2. The Issuer Server can optionally repeat this process to trigger the collection of additional Verification.
  5. After reaching a verdict the Issuer Server updates the verification status and notifies the Wallet Server of the change.

On successful completion the Issuer Server now has a WSK that can be used to authenticate payloads as originating on a particular Wallet Client Instance, and have authenticated the Holder.

The Wallet retrieves the credentials as follows:

  1. The Wallet Server retrieves the Credential Ids from the Wallet Server using the Wallet Id and Verification Id.
  2. The Wallet Client generates proofs for Presentation Keys and signs-then-encrypts them using the WSK and the Issuer encryption key. The Wallet Client also creates an encryption key and signs it with the WSK.
  3. The Wallet Server retrieves a batch of Credentials using the Credential Ids and the client payload.

    1. The Credentials can be retrieved asynchronously by the Issuer Server returning a PENDING state.
  4. The Issuer verifies the keys originated on the correct client using the WSK, validates the proofs and creates the Credentials. The Credentials are encrypted using the Wallet Encryption Key before being sent back to the Wallet.

    1. Credential Metadata, such as display can optionally be returned as well.

This process is repeated to refresh the Credentials and to update them. Post initial issuance, Credentials lifecycle can be managed through the following processes:

5. Endpoints

This specification defines a series of endpoints on both the Wallet Server and the Issuer Server. Endpoints.

Table 1
Endpoint Path Implemented By Description
Verification Initiate /verification/initiate Issuer Starts the verification process for a Wallet Client Instance for a particular set of credential configurations.
Verification Supplement /verification/supplement Issuer Provides additional verification data for an ongoing verification session.
Get Verification Status /verification/status Issuer Queries the current status of a verification session.
Verification Notification /verification/notify Wallet Allows the Issuer to notify the Wallet of a verification status change.
Verification Cancellation /verification/cancel Issuer Cancels an ongoing verification session.
Provision Credentials /credential/provision Issuer Fetches Credential Ids after verification approval.
Get Credential /credential/get Issuer Retrieves the verifiable credentials for a particular Credential Id.
Get Credential Metadata /credential/metadata Issuer Retrieves metadata for a specific credential configuration.
Get Credential Status /credential/status Both Bidirectional endpoint to query the current status of a Credential.
Credential Management /credential/manage Both Handles ongoing management and lifecycle operations for a Credential.
Event Notification /event/notify Both Bidirectional poke channel for action-based notifications.

The following requirements apply to all endpoints.

5.1. Server Authentication

All endpoints MUST use mutual TLS (mTLS) as the authentication method between the Wallet and Issuer Servers, as described by [RFC8705]. Both servers present X.509 client certificates during the TLS handshake. Certificate management is outside of scope of this specification.

Issuers MUST associate a Wallet Id with the mTLS client identity that created it and reject requests for that Wallet Id from any other identity.

5.2. Transport

All requests to endpoints MUST use HTTPS (TLS 1.2+) with mutual authentication. All requests and response bodies are JSON and MUST use the media type application/json.

TODO: should add things about gRPC migration

5.3. API Versioning

The API uses header-based semantic versioning. The Client MUST include the desired API version in the Api-Version request header using the semantic version (e.g. 1.0.0).

The following header is used in requests to specify the desired API version:

Table 2
Header Type Description
Api-Version String (semantic version) Required. Semantic version requested by the client (e.g., 1.0.0)

The following headers are used in responses to convey information about the API version used or supported by the server:

Table 3
Header Type Description
Api-Version String (semantic version) Required. The version used to process the request
Api-Supported-Versions String (comma-separated versions) Comma-separated list of versions the server supports
Sunset String (HTTP-date) HTTP-date as defined in [RFC8594] after which the requested version will be removed

Server MUST reject requests with an unsupported Api-Version with HTTP 400 and a Problem Details response, indicating the supported versions in the header.

5.4. Error Handling

This API uses Problem Details for HTTP APIs [RFC9457] for all error responses. Success responses return clean payloads without error wrappers.

Error responses use content type application/problem+json and MAY include:

Table 4
Field type Description
type URI Machine-readable error type identifier (e.g., urn:credential-api:error:verification-expired)
title string Short human-readable summary of the error type
status integer HTTP status code
detail string Human-readable explanation specific to this occurrence
instance URI URI identifying this specific error occurrence (for support/debugging)

Implementations MAY extend the Problem Details object with additional fields (e.g., error_code for machine-readable application codes, retryable flag, validation_errors array for field-level issues). See Section 3.1 of [RFC9457] for more information.

5.4.1. Error Types

This specification defines the following error types:

  • urn:openid:dcp:s2s:invalid_encryption: Error type returned when a payload fails to decrypt.
  • urn:openid:dcp:s2s:invalid_client_authentication: Error type returned when a Client Encrypted Payload verification fails.

5.5. End to End Encryption

All application-layer encryption is performed using JWE [RFC7516] with HPKE [RFC9180] key encapsulation, as defined in [I-D.ietf-jose-hpke-encrypt].

5.5.1. JweEncryptedPayload

The JweEncryptedPayload is the data structure used to represent an encrypted payload in the API.

Table 5
Field Type Description
jwe string/object (JWE) REQUIRED: JWE structure as either compact or json serialized. When the origin is
origin string (Enum) REQUIRED: Identifies the origin of the encryption (one of WALLET_CLIENT, WALLET_SERVER, or ISSUER).
purpose string OPTIONAL: Optional purpose hint.
extensions object OPTIONAL: Implementation-specific extension fields.

The JWE MUST include the alg and enc parameters. Additionally, if the jwk used in encryption included a kid it MUST include the kid parameter. When the origin is WALLET_CLIENT then the content MUST be a JWS (as specified in Client Encrypted Payloads section).

5.5.2. Client Encrypted Payload

Client Encrypted Payloads are sign-then-encrypted, to provide confidentiality and sender authentication. This MUST be used when the origin is WALLET_CLIENT. This is achieved using a nested JWT. The outer JWT is a JWE as described above, whose plaintext is a JWS [RFC7515]. The JWS is signed using the Wallet Client signing key.

The aud claim of the JWS payload MUST be set to the base64url encoded JWK SHA-256 thumbprint [RFC7638] of the key that is used to encrypt the Client Encrypted Payload.

When receiving a payload containing Wallet Client Encryption the Issuer MUST process it as follows:

  • Decrypt the outer JWE.
  • Verify the signature of the JWS matches the previously established Wallet Signing Key.
  • Verify that the aud matches the base64url encoded JWK SHA-256 thumbprint used to encrypt the outer JWE.

If this process fails for any received Client Encrypted Payload the Issuer MUST reject the request.

5.5.3. KeyData

All keys are communicated between the Wallet and Issuer using this common key structure.

Table 6
Field Type Description
key_type string REQUIRED: Semantic use for the key.
client_public_key object (JWK) REQUIRED: The public key in the JWK format as defined in [RFC7517].
attestation Object (Proof) OPTIONAL: Attestation about the key. For example a platform-provided x509-chain or a keyattestation-jwt.
purpose string OPTIONAL: Human-readable purpose of the key.
extensions object OPTIONAL: Implementation-specific extension fields.

The client_public_key JWK MUST include the alg identifier and is RECOMMENDED to include a kid.

This specification defines two key types:

  • WALLET_SIGNING_KEY: Key used by the Wallet Client Instance as a proof-of-origin
  • WALLET_ENCRYPTION_KEY: Key provided by the Wallet Client Instance for the Issuer to encrypt sensitive data to.

Implementations MAY define their own key types. It is RECOMMENDED that collision-resistant values are used, such as r-DNS or urns.

TODO: add post quantum

TODO: required curves

5.6. Content Reference

This section details how large content can be passed by reference to a downloadable URL, rather than by value.

Table 7
Field Type Description
download_url string (URI) REQUIRED: The URL where the content can be downloaded.
content_digest string (byte) REQUIRED: SHA-256 digest of the JWE content.
content_size integer OPTIONAL: The size of the content in bytes.
expires_at string (date-time) OPTIONAL: The timestamp after which the URL expires.
extensions object OPTIONAL: Implementation-specific extension fields.

5.7. Idempotency

All requests MUST include the x-request-id header (UUID). Duplicate requests with the same value MUST return the original response without re-executing the operation.

5.8. Rate Limiting

Clients receiving HTTP 429 MUST honor the Retry-After header. Exponential backoff is RECOMMENDED: 0–1s, 1.1–5s, 5.1–30s (max 3 retries).

5.9. Identifier Model

The API uses the following identifiers:

  • Wallet Id: A unique identifier, generated by a Wallet on initiating Verification with an Issuer. It persists across all subsequent interactions (including multiple Verifications and Credentials), identifying that Wallet Client Instance to that Issuer. A new initiation between the same Wallet and Issuer can result in a different Wallet Id.
  • Verification Id: An identifier for a particular verification session. A Wallet Id may have multiple Verification Ids associated with it over the course of its lifetime (due to re-verification).
  • Credential Id: An identifier for a Credential Dataset that an Issuer has issued, or can issue, to a particular Wallet Client Instance. Each Credential Id corresponds to a single Credential Configuration and has a 1:1 relationship with a credential status. A Credential Id can cover a batch of Credentials, in which case the status of individual Credentials within the batch cannot be changed independently. A single Wallet Id and Verification Id may result in multiple Credential Ids being issued associated with that Wallet Id (e.g. multiple digital payment credentials all issued for a single bank account).
  • Credential Configuration Id: An identifier for a particular type/configuration of a credential at an issuer, as defined in OpenID4VCI. A single verification session can be used to issue multiple different Credential Configurations.

All identifiers are opaque strings assigned by the Issuer, with the exception of the Wallet Id, which is generated by the Wallet. No format, prefix, or structure is enforced by this specification. Implementations may define conventions (e.g., prefixed UUIDs) but interoperability does not depend on identifier structure.

A Wallet Id MUST be unique between a Wallet Provider and an Issuer. A Credential Id MUST be unique for an Issuer. Verification Ids and Credential Ids MUST be unique for a given Wallet Id.

5.10. Verification Endpoints

The Verification endpoints are used to determine that a particular Wallet Client Instance authorized to have a Credential. This encompasses Identity Proofing, (e.g., document authentication, liveness detection, facial matching for government IDs), eligibility verification (e.g., fraud scoring, account standing checks for payment cards, access badges) as well as transferring Verification from another context (pre-auth code, device migration).

5.10.1. Engagement

There are five different flows we are considering in this specification:

  1. Wallet Initiated (Preknown Verification): Holder in a Wallet Client Instance, where the Issuer's required VerificationData is known in advance.
  2. Wallet Initiated (Negotiated Verification): Holder in a Wallet Client Instance, where the Issuer's required Verification Data is unknown
  3. Issuer Initiated (Authed Holder): Holder is in an Issuer Surface (e.g. Issuer App) where the holder is already authenticated. The Holder wishes to push one or more credentials to a Wallet Client Instance of their choosing.
  4. Issuer Initiate (Unauthed Holder): Holder is in an Issuer Surface (e.g. Issuer Website) but are not currently (sufficiently) authenticated. The Holder wishes to initiate a Wallet Client Instance and begin Issuance of some Credentials.
  5. Device Migration: Holder in a new Wallet Client Instance, but has previously performed Verification in another Wallet Client Instance.

All engagement is modeled as the Wallet receiving a Credential Offer payload from the Issuer.

This could be obtained:

  • Via a front-channel, such as DC API create, a deep-link or a QR code.
  • Via a back-channel call from the Issuer Server to the Wallet Server

    • Though this is currently out of scope of this specification
5.10.1.1. Credential Offer Payload Schema

TODO: Determine the best way to pass Pre-Auth/VerificationDataRequest/Issuer State, whether to re-use what is in canonical VCI or extend it

5.10.2. Verification Initiate

The path MUST be /verification/initiate. This endpoint is hosted by the Issuer Server only.

The Verification Initiate endpoint is the first endpoint called by the Wallet Server, and starts the verification process for a Wallet Client Instance.

5.10.2.1. Wallet Id Establishment

The Wallet provides a long-lived Wallet Id, identifying the Wallet Client Instance, to associate with the WalletSigningKey. The Issuer provides the Verification Id in the response, which is used for follow-up calls to the Verification Endpoints.

Credential Ids are retrieved after verification through the Credential Provision endpoint.

5.10.2.2. Replay Protection

This endpoint is protected against replay attacks through a signed nonce mechanism. The wallet produces a digital signature over the Wallet Id using the Wallet Signing Key and includes this signature as the verification_nonce field in the request.

Issuers MUST perform the following verification steps:

  • Verify the verification_nonce signature using the Wallet Signing Key included in the same request
  • Confirm the signed value matches the wallet_id in the request
  • Confirm the wallet_id value has not been previously consumed

Because each Wallet Id is a unique UUID generated on calling Initiate, a replayed request will be rejected — either the Wallet Id was already consumed, or a different Wallet Id will not match the original signature. Replay from a different device is also prevented, as only the holder of the private Wallet Signing Key can produce a valid signature.

5.10.2.3. Request Body Schema:
Table 8
Field Type Description
wallet_id string(UUID) REQUIRED: Wallet-generated UUID identifying this Wallet Client Instance. Shared correlation identifier that threads verification and credential issuance.
credential_configuration_ids Array (string) REQUIRED: Identifies the credential types/templates for the credentials being requested.Issuers use this to determine which credential type and configuration apply.
wallet_signing_key_data object (KeyData) REQUIRED: Key Data belong to the Public Key for the Wallet Client Instance that is initiating this verification.Must be stored against this wallet_id and used to verify this and subsequent requests originate from the same authenticated client instance.
verification_nonce string(bytes) REQUIRED: Signature over wallet_id, providing replay protection and cryptographic binding to the Wallet Id.
verification_data Object (VerificationDataResponse) OPTIONAL: VerificationDataResponse to allow for Wallets to combine providing evidence when it is known in advance.
supported_verification_types Array(String) OPTIONAL: List of verification_types this Wallet Client Instance supports, that can be used with ADDITIONAL_INFO_REQUIRED
requested_device_count integer >=1 (default 1) OPTIONAL: Number of devices the Wallet Server intends to provision for this verification session. The issuer uses this as input when determining authorized_device_count in the approval response. If omitted, defaults to 1.
locale string OPTIONAL: Local of the Wallet Client Instance to use for localization. When absent, the Issuer chooses the locale.
extensions object OPTIONAL: Implementation-specific extension fields. Reserved for proprietary data elements needed by specific deployments.
5.10.2.4. Response Body Schema:

The Response Body schema contains all of the fields in the VerificationStatus schema.

5.10.3. Supplement

The path MUST be /verification/supplement. This endpoint is hosted by the Issuer Server only.

This is used to provide Verification Data for an ongoing Verification.

5.10.3.1. Request Body Schema
Table 9
Field Type Description
wallet_id string(UUID) REQUIRED: Wallet-Generated id received in the initiate call.
verification_id string(UUID) REQUIRED: Issuer-generated id for the current verification session.
verification_data Object (VerificationDataResponse) REQUIRED: Containing verification data for this verification session.
extensions Object OPTIONAL: Implementation-specific extension fields.
5.10.3.2. Response Body Schema

The Response Body schema contains all of the fields in the VerificationStatus schema.

5.10.4. Verification Notification

The path MUST be /verification/notify. This endpoint is hosted by the Wallet Server only.

This is used by the Issuer to notify the Wallet that a Verification has changed status. The information provided here is also available at the Verification Status Endpoint.

5.10.4.1. Request Body Schema

The Request Body contains allOf the fields in the VerificationStatus schema.

5.10.4.2. Response Body Schema
Table 10
Field Type Description
wallet_id string(UUID) REQUIRED: Wallet-Generated id received in the initiate call.
verification_id string(UUID) REQUIRED: Issuer-generated id for the current verification session.

5.10.5. Get Verification Status

The path MUST be /verification/status. This endpoint is hosted by the Issuer Server only.

5.10.5.1. Request Body Schema
Table 11
Field Type Description
wallet_id string(UUID) REQUIRED: Wallet-Generated id received in the initiate call.
verification_id string(UUID) REQUIRED: Issuer-generated id for the current verification session.
extensions Object OPTIONAL: Implementation-specific extension fields.
5.10.5.2. Response Body Shema

The Response Body contains allOf the fields in the VerificationStatus schema.

5.10.6. Verification Cancellation

The path MUST be /verification/cancel. This endpoint is hosted by the Issuer Server only.

5.10.6.1. Request Body Schema
Table 12
Field Type Description
wallet_id string(UUID) REQUIRED: Wallet-Generated id received in the initiate call.
verification_id string(UUID) REQUIRED: Issuer-generated id for the current session.
reason string REQUIRED: Indicates the reason for cancellation.
extensions Object OPTIONAL: Implementation-specific extension fields.
5.10.6.2. Response Body Schema
Table 13
Field Type Description
wallet_id string(UUID) REQUIRED: Wallet-Generated id received in the initiate call.
verification_id string(UUID) REQUIRED: Issuer-generated id for the current session.

5.10.7. Verification Status

A Verification is often a long-lived process, and the VerificationStatus is used to represent the current state of the Verification. The Issuer Server is the single source of truth for the Verification.

The current VerificationStatus is returned from both the Initiate and Supplement Verification endpoints. Changes to the VerificationStatus are communicated using a poke model, where the Issuer notifies the Wallet Server on change, and the current status can also be polled by the Wallet Server.

The following JSON Schema is used at all endpoints:

5.10.7.1. VerificationStatus Schema
Table 14
Field Type Description
wallet_id string(UUID) REQUIRED: Wallet-Generated id received in the initiate call.
verification_id string(UUID) REQUIRED: Issuer-generated id for the current session. The value MUST NOT change from the one returned in the initial response..
status string(VerificationStatus) REQUIRED: Enum identifier for the current verification status.
extensions Object OPTIONAL: Implementation-specific extension fields. Implementations may include proprietary decision details, additional credential metadata, or domain-specific status information.

Additional fields are specified based on the VerificationStatus. The following VerificationStatus values are defined by this specification:

Table 15
Status Description Next Step
"APPROVED" Verification Passed Wallet Server calls /credential/provision to fetch the Credential Ids
"REJECTED" Most recent Verification Data was rejected. Wallet re-collects Verification Data and re-submit or cancel the verification
"DENIED" Verification Failed Flow ends
"ADDITIONAL_INFO_REQUIRED" Issuer requires more Verification Data Wallet Server calls verification/supplement with additional Verification Data.
"PENDING" Decision Deferred The wallet waits for status to change.
"EXPIRED" Verification Session Timed out Flow ends

The following fields are present based on type:

5.10.7.1.1. APPROVED Status Fields
Table 16
Field Type Description
credential_configuration_ids Array (string) REQUIRED: Credential Configurations that
authorized_device_count Integer (>=1), default=1 OPTIONAL: Maximum number of devices this Wallet Id/Verification Id can be used on, after which the Issuer SHOULD reject any further attempts.
5.10.7.1.2. REJECTED Status Fields
Table 17
Field Type Description
reason_code string REQUIRED: Rejection reason code.
rejected_details string OPTIONAL: Details for logging.
5.10.7.1.3. DENIED Status Fields
Table 18
Field Type Description
reason_code string REQUIRED: Denial reason code.
denied_message string REQUIRED: Message for the human.
5.10.7.1.4. ADDITIONAL_INFO_REQUIRED Status Fields
Table 19
Field Type Description
verification_data_request Object (VerificationDataRequest) REQUIRED: Used to collect additional information from the holder.

5.10.8. Verification Data

Verification Data is an extensible mechanism for a Wallet to provide the Issuer with Data used to determine that a Credential can be issued to the Wallet Client Instance. This can include information both originating from the Wallet Client and the Wallet Server. Examples include:

  • Verifiable Digital Credential presentations
  • Wallet-collected documents
  • Auth via a redirect to web or other issuer surface
  • Pre-auth bearer token binding this session to another
  • Previous Wallet Id/Verification Ids to associate this Wallet Client Instance with a previous one
  • Risk or other attestation signals from the Wallet Server

The flow is as follows:

  1. [upfront] Wallet communicates the supported_verification_types
  2. Issuer Server provides a VerificationDataRequest detailing the requested Data

    • This is optional if pre-known by the Wallet
  3. The Wallet Client performs the necessary actions to collect the required Data from the Holder, and passes it, encrypted, to the Wallet Server.
  4. The Wallet Server adds any additional VerificationData and provides a VerificationDataResponse to the Verification Supplement endpoint.
  5. The Issuer decrypts and verifies the client_encrypted_payload and then (asynchronously) processes the response.
  6. The Issuer repeats steps 2-5 until it reaches a final decision.
5.10.8.1. VerificationDataRequest Schema
Table 20
Field Type Description
verification_data_items Array (VerificationDataItemRequest) REQUIRED: Array of items requested
deadline string (date-time) OPTIONAL: deadline for the request, after which the Verification will be DENIED.
max_attempts integer OPTIONAL: Maximum number of attempts allowed, after which the Verification will be DENIED.
extensions object OPTIONAL: Implementation-specific extension fields
5.10.8.2. VerificationDataItemRequest Schema
Table 21
Field Type Description
type string REQUIRED: Type of the Verification item
id string REQUIRED: Unique identifier for the item
required boolean REQUIRED: Whether this VerificationDataItem MUST be provided.
extensions object OPTIONAL: Implementation-specific extension fields..

Additional type-specific fields MAY be required based on verification type. It is RECOMMENDED to use collision-resistance values for verification type such as URNs or r-DNS.

TODO: define default ones.

5.10.8.3. VerificationDataResponse Schema
Table 22
Field Type Description
client_encrypted_payload Array (JweEncryptedPayload (VerificationDataItem)) OPTIONAL: Encrypted payload originating from the Wallet Client, containing a VerificationDataItem.
server_verification_data_item Array (VerificationDataItem) OPTIONAL: Verification items provided by the Wallet Server.
additional_assessments Array (object) OPTIONAL: Additional risk or eligibility assessments from the Wallet Server.
extensions object OPTIONAL: Implementation-specific extension fields.

client_encrypted_payload contains the WALLET_CLIENT originating VerificationDataItem, while server_verification_data_item contains ones that originate in the WALLET_SERVER backend. A VerificationDataItem MAY be present in both, in the case where part of the data comes from one system and part from another.

The Issuer MUST verify the client_encrypted_payload using the WalletSigningKey associated with the Wallet Id before proceeding to evaluate the VerificationDataItem.

5.10.8.4. VerificationDataItem Schema
Table 23
Field Type Description
id string REQUIRED: Unique identifier for the item.
type string REQUIRED: Type of the Verification item.
extensions object OPTIONAL: Implementation-specific extension fields.

Additional type-specific fields MAY be required based on verification type. It is RECOMMENDED to use collision-resistance values for verification type such as URNs or r-DNS.

5.11. Credential Endpoints

These endpoints are used to initially retrieve a Credential onto a Holders device, as well as to fetch new Credentials as needed.

In addition they also control the lifecycle through the Get Credential Status and Manage Credential endpoints.

5.11.1. Provision Credential

This endpoint is used to fetch Credential Ids after verification approval. The path MUST be /credential/provision.

5.11.1.1. Request Body Schema
Table 24
Field Type Description
wallet_id string (UUID) REQUIRED: Wallet-generated UUID for this Wallet Client Instance.
verification_id string (UUID) REQUIRED: Issuer-generated id for the current session.
extensions object OPTIONAL: Implementation-specific extension fields.
5.11.1.2. Response Body Schema
Table 25
Field Type Description
provisioned_credentials Array (object) REQUIRED: Array of objects containing a credential configuration and its Credential Ids.
extensions object OPTIONAL: Implementation-specific extension fields.

Each provisioned_credentials object contains:

  • credential_configuration_id: (string, required)
  • credential_ids: (Array (string), required)

5.11.2. Get Credential

This endpoint is used to retrieve the verifiable credentials for a specific Credential Id. The path MUST be /credential/get.

5.11.2.1. Request Body Schema
Table 26
Field Type Description
wallet_id string REQUIRED: Identifier for the Wallet Client Instance.
credential_id string REQUIRED: Credential Id.
reason string REQUIRED.: Reason for the Wallet initiating the credential fetch, for debugging purposes.
wallet_encryption_key object (KeyData) REQUIRED: Key provided for the Issuer to encrypt sensitive data to.
client_encrypted_payload object (ClientEncryptedPayload) OPTIONAL: Payload containing an object containing an array of presentment_keys.
current_credential_metadata_version string OPTIONAL: Current Version identifier for the credential metadata.
extensions object OPTIONAL: Implementation-specific extension fields.
5.11.2.2. Response Body Schema
Table 27
Field Type Description
credential_metadata object (CredentialMetadata) OPTIONAL: Metadata for the specific credential configuration.
credential_version string REQUIRED: Unique identifier for the credential data set version.
credentials object (JWE) REQUIRED: JWE object whose plaintext is an Array of Credentials.
extensions object OPTIONAL: Implementation-specific extension fields.

5.11.3. Get Credential Metadata

This endpoint retrieves metadata for a specific credential configuration. The path MUST be /credential/metadata.

5.11.3.1. Request Body Schema
Table 28
Field Type Description
wallet_id string REQUIRED: Identifier for the Wallet Client Instance.
credential_id string REQUIRED: Credential Id.
wallet_encryption_key object (KeyData) REQUIRED: Key provided for the Issuer to encrypt sensitive data to.
credential_metadata_version string OPTIONAL: Version identifier for the requested metadata.
extensions object OPTIONAL: Implementation-specific extension fields.
5.11.3.2. Response Body Schema
Table 29
Field Type Description
credential_metadata object (CredentialMetadata) OPTIONAL: Metadata for the specific Credential. Includes display_data as well as other relevant metadata.
extensions object OPTIONAL: Implementation-specific extension fields.

5.11.4. Get Credential Status

The Get Credential Status endpoint is a bidirectional endpoint that provides the current status from the perspective of that server.

The path MUST be /credential/status.

5.11.4.1. Reconciliation

The Wallet Server and the Issuer Server each have their own view on what the status of the credential should be. The Response provides sufficient information to allow the calling server to be aware as to what action should be taken to reconcile the different states.

(TODO: Add a grid defining what next step should be taken?).

5.11.4.2. Request Body Schema
Table 30
Field Type Description
wallet_id string REQUIRED: Identifier for the Wallet Client Instance being queried.
credential_id string REQUIRED: Credential Id whose status is being queried.
extensions object OPTIONAL: Implementation specific extensions
5.11.4.3. Response Body Schema
Table 31
Field Type Description
current_status String (CredentialStatus) REQUIRED: The current status of the credential
current_version String REQUIRED: Unique identifier for the credential data set version.
last_status_change_time String (HTTP-date) OPTIONAL: Date and time when the status was last updated
last_status_change_reason String OPTIONAL: Machine-readable reason for the status change
extensions Object OPTIONAL: Implementation-specific extension fields

The following Credential Status states are defined by this specification.

Table 32
Status Description
ACTIVE Credential is active and usable
SUSPENDED_ISSUER Suspended by the credential issuer
SUSPENDED_WALLET Suspended by the wallet operator
UNLINKED Credential removed from device
IN_PROCESS Provisioning or lifecycle operation in progress
CANCELLED Credential permanently invalidated
UNKNOWN Status cannot be determined

5.11.5. Credential Manage

This bi-directrional endpoint instructs the hosting party to perform an action for a particular credential_id. The path MUST be /credential/manage.

5.11.5.1. Request Body Schema
Table 33
Field Type Description
wallet_id string (UUID) REQUIRED: Wallet-generated UUID for this Wallet Client Instance.
credential_id string REQUIRED: Credential Id associated with this management operation.
action string (Enum) REQUIRED: The management action to perform. One of: SUSPEND, RESUME, UNLINK.
reason string OPTIONAL: Machine-readable reason for the management action.
reason_detail string OPTIONAL: Free-form additional context or details for the action.
timestamp string (date-time) OPTIONAL: ISO 8601 timestamp of when the request was initiated.
extensions object OPTIONAL: Implementation-specific extension fields.
5.11.5.2. Response Body Schema
Table 34
Field Type Description
wallet_id string (UUID) REQUIRED: Wallet-generated UUID for this Wallet Client Instance.
credential_id string REQUIRED: Credential Id associated with this management operation.
current_status string (CredentialStatus) REQUIRED: The status of the credential after the operation.
previous_status string (CredentialStatus) OPTIONAL: The status of the credential before the operation was initiated.
outcome string (Enum) REQUIRED: The outcome of the operation. One of: COMPLETED, SCHEDULED, FAILED, NO_CHANGE.
failure_reason string OPTIONAL: Machine-readable reason for failure if the outcome is failed.
extensions object OPTIONAL: Implementation-specific extension fields.

5.12. Event Notification Endpoint

This endpoint is used to provide a bidirectional notification channel between the Wallet Server and the Issuer Server. All notifications follow the poke model, describing an action to be performed by the recipient, but not containing unrecoverable data.

The path MUST be /event/notify and implemented by both the Wallet Server and the Issuer Server.

5.12.1. Request Body Schema

Table 35
Field Type Description
wallet_id string REQUIRED: Identifier for the Wallet Client Instance.
credential_id string REQUIRED: Credential Id associated with the event.
event_type string REQUIRED: The type of event being notified.
triggering_request_id string (UUID) OPTIONAL: The x-request-id of the original request that triggered this event.
event_timestamp string (date-time) REQUIRED: The timestamp when the event was created.
event_details object TYPE DEPENDENT: Implementation-specific details dependent on the event_type.
extensions object OPTIONAL: Implementation-specific extension fields.

5.12.2. Event Types

The following event types are defined by this specification:

Table 36
Event Origin Description
PROVISIONING_SUCCESS Wallet Server Credential successfully provisioned to device
PROVISIONING_FAILURE Wallet Server Credential provisioning failed
LIFECYCLE_SUCCESS Wallet Server Lifecycle action completed
LIFECYCLE_FAILURE Wallet Server Lifecycle action failed
UPDATE_SUCCESS Wallet Server Credential update applied to device
UPDATE_FAILURE Wallet Server Credential update failed
UPDATE_REMINDER Wallet Server Pending update awaiting delivery
CREDENTIAL_EXPIRING Wallet Server Credential approaching expiry
KEY_ROTATED Wallet Server Device generated new presentment keys
CREDENTIAL_READY Issuer Async credential is ready for retrieval
CREDENTIAL_UPDATE_AVAILABLE Issuer Updated credential data available for retrieval
DISPLAY_DATA_UPDATED Issuer Visual representation has changed

TODO: Add the detailed schemas by type

5.12.3. Response Body Schema

The response body schema optionally contains an acknowledged boolean to indicate that the event was processed.

6. Issuer Metadata

TODO: work out what needs to be configurable. E.g. issuer_server_url, configurations, supported_signing_algs, supported_encryption_algs, issuer_encryption_jwks, supported_extensions, and what comes from VCI spec s.a supported_proofs etc.

7. Security Considerations

7.1. Wallet Client Origin

This specification makes use of a Wallet Signing Key to authenticate payloads originating from the Wallet Client. As part of Verification, the Wallet Signing Key signs-and-encrypts Verification Data, demonstrating to the Issuer that the Verification Data was collected in the presence of the Wallet Signing Key. How strongly that Data types the Wallet Signing Key depends on the specifics of the issuance process and is outside the scope of this specification.

7.2. Wallet Client and Wallet Client Instance Trust

This specification delegates the decision about whether a Wallet Client, or a specific instance of it, can be trusted, and to what extent, to the Wallet Server. For example, the Wallet Server can securely verify the Wallet Client's integrity using platform-level hardware checks before executing any lifecycle actions. The exact mechanism for determining Wallet Client trust is out of scope for this specification, but must be considered by implementers.

7.3. Pre-authorization Code security measures

It is important to note that anyone with a valid Pre-Authorized Code, without additional security measures, can receive a Credential from the Credential Issuer. Implementers MUST implement the mitigations most suitable to the use case.

8. Privacy Considerations

8.1. Data Minimization

By design, the Wallet Server is always aware of what types of Credentials and the Issuers that a Wallet Holder is interacting with. This is necessary for the Wallet Server to provide value to the Issuer and the Holder. The specification is however designed with the principle of Data Minimization, where application layer encryption combined with sender authentication (using the Wallet Signing Key) is used to ensure confidentiality of the sensitive portions of the payload that are not required by the Wallet Server.

9. Implementation Considerations

9.1. Asynchronous Endpoints

The APIs are designed so that the Verification and Credential endpoints operate asynchronously. Wallet Servers MUST support returning responses both immediately and asynchronously in the future. As notifications are unreliable, it's RECOMMENDED that Wallet Servers use both notifications and polling-with-backoff to receive results from these endpoints as quickly and reliably as possible.

Because these endpoints are asynchronous, Wallet Clients need to be able to handle receiving the results asynchronously as well. The API between the Wallet Client and Server is outside the scope of this specification, but it would be advisable to adopt a similar approach between the Wallet Client and Server.

9.2. Extensions

The API in this specification defines extension points throughout the protocol, using an extensions object. It is RECOMMENDED to use collision-resistant field names within the extension, such as r-DNS or urns. To maximize interoperability, Wallets and Issuers are RECOMMENDED to ignore unknown extensions, and process the Requests or Responses as though they aren't present

10. Normative References

[I-D.ietf-jose-hpke-encrypt]
Reddy.K, T., Tschofenig, H., Banerjee, A., Steele, O., and M. B. Jones, "Use of Hybrid Public Key Encryption (HPKE) with JSON Web Encryption (JWE)", Work in Progress, Internet-Draft, draft-ietf-jose-hpke-encrypt-22, , <https://datatracker.ietf.org/doc/html/draft-ietf-jose-hpke-encrypt-22>.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC7515]
Jones, M., Bradley, J., and N. Sakimura, "JSON Web Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, , <https://www.rfc-editor.org/info/rfc7515>.
[RFC7516]
Jones, M. and J. Hildebrand, "JSON Web Encryption (JWE)", RFC 7516, DOI 10.17487/RFC7516, , <https://www.rfc-editor.org/info/rfc7516>.
[RFC7517]
Jones, M., "JSON Web Key (JWK)", RFC 7517, DOI 10.17487/RFC7517, , <https://www.rfc-editor.org/info/rfc7517>.
[RFC7638]
Jones, M. and N. Sakimura, "JSON Web Key (JWK) Thumbprint", RFC 7638, DOI 10.17487/RFC7638, , <https://www.rfc-editor.org/info/rfc7638>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/info/rfc8174>.
[RFC8594]
Wilde, E., "The Sunset HTTP Header Field", RFC 8594, DOI 10.17487/RFC8594, , <https://www.rfc-editor.org/info/rfc8594>.
[RFC8705]
Campbell, B., Bradley, J., Sakimura, N., and T. Lodderstedt, "OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens", RFC 8705, DOI 10.17487/RFC8705, , <https://www.rfc-editor.org/info/rfc8705>.
[RFC9180]
Barnes, R., Bhargavan, K., Lipp, B., and C. Wood, "Hybrid Public Key Encryption", RFC 9180, DOI 10.17487/RFC9180, , <https://www.rfc-editor.org/info/rfc9180>.
[RFC9457]
Nottingham, M., Wilde, E., and S. Dalal, "Problem Details for HTTP APIs", RFC 9457, DOI 10.17487/RFC9457, , <https://www.rfc-editor.org/info/rfc9457>.

11. Informative References

[I-D.ietf-oauth-sd-jwt-vc]
Terbu, O., Fett, D., and B. Campbell, "SD-JWT-based Verifiable Digital Credentials (SD-JWT VC)", Work in Progress, Internet-Draft, draft-ietf-oauth-sd-jwt-vc-26, , <https://datatracker.ietf.org/doc/html/draft-ietf-oauth-sd-jwt-vc-26>.
[ISO.18013-5]
ISO/IEC JTC 1/SC 17 Cards and security devices for personal identification, "ISO/IEC 18013-5:2021 Personal identification — ISO-compliant driving licence — Part 5: Mobile driving licence (mDL) application", , <https://www.iso.org/standard/69084.html>.
[VC_DATA_2.0]
Sporny, M., Jr, T. T., Herman, I., and G. Cohen, "Verifiable Credentials Data Model 2.0", , <https://www.w3.org/TR/2025/REC-vc-data-model-2.0-20250515/>.

Appendix A. Verification Flow Examples

A.1. Wallet Initiated (Preknown Verification)

A non-normative example of a Wallet Initiated(Preknown Verification) Flow is:

┌────────┐            ┌───────────────┐       ┌───────────────┐               ┌───────────────┐
│ Holder │            │ Wallet Client │       │ Wallet Server │               │ Issuer Server │
└────┬───┘            └───────┬───────┘       └───────┬───────┘               └───────┬───────┘
     │                        │                       │                               │
     │     1. Selects a       │                       │                               │
     │  Credential to Issue   │                       │                               │
     │────────────────────────▶                       │                               │
     │                        │                       │                               │
     │                        ├───┐                   │                               │
     │                        │   │ Generates WSK &   │                               │
     │                        │   │ collects          │                               │
     │                        │   │ VerificationData  │                               │
     │                        ◀───┘                   │                               │
     │                        │                       │                               │
     │                        │                       │                               │
     │                        │                       │                               │
     │                        │       2. Sends        │                               │
     │                        │   Signed/Encrypted    │                               │
     │                        │  VerificationData +   │                               │
     │                        │  verification_nonce   │                               │
     │                        │╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▶                               │
     │                        │                       │                               │
     │                        │                       ├───┐                           │
     │                        │                       │   │ Adds additional           │
     │                        │                       │   │ VerificationData          │
     │                        │                       ◀───┘                           │
     │                        │                       │                               │
     │                        │                       │                               │
     │                        │                       │           3. Calls            │
     │                        │                       │    'verification/initiate'    │
     │                        │                       │───────────────────────────────▶
     │                        │                       │                               │
     │                        │                       │                               ├───┐
     │                        │                       │                               │   │ Validates
     │                        │                       │                               │   │ verification_nonce &
     │                        │                       │                               │   │ client_encrypted_payload
     │                        │                       │                               ◀───┘
     │                        │                       │                               │
     │                        │                       │                               │
     │                        │                       │                               │
     │                        │                       │      4. status: PENDING       │
     │                        │                       ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│
     │                        │                       │                               │
     │                        │                       │                               ├───┐
     │                        │                       │                               │   │ Asynchronously
     │                        │                       │                               │   │ evaluates
     │                        │                       │                               ◀───┘ VerificationData
     │                        │                       │                               │
     │                        │                       │                               │
     │                        │                       │                               │
     │                    ┌opt [4.1. Additional Verification]─────────────────────────────┐
     │                    │   |                       │                               │   │
     │                    │   │                       │    'verification/notify':     │   │
     │                    │   │                       │   ADDITIONAL_INFO_REQUIRED    │   │
     │                    │   │                       ◀───────────────────────────────│   │
     │                    │   │                       │                               │   │
     │                    │   │   Sends additional    │                               │   │
     │                    │   │   Signed/Encrypted    │                               │   │
     │                    │   │   VerificationData    │                               │   │
     │                    │   │╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▶                               │   │
     │                    │   │                       │                               │   │
     │                    │   │                       │  'verification/supplement':   │   │
     │                    │   │                       │          additional           │   │
     │                    │   │                       │       VerificationData        │   │
     │                    │   │                       │───────────────────────────────▶   │
     │                    │   │                       │                               │   │
     │                    └───────────────────────────────────────────────────────────────┘
     │                        │                       │                               │
     │                        │                       │                               ├───┐ Updates
     │                        │                       │                               │   │ Verification
     │                        │                       │                               ◀───┘ Status
     │                        │                       │                               │
     │                        │                       │                               │
     │                        │                       │              5.               │
     │                        │                       │    'verification/notify':     │
     │                        │                       │        APPROVED/DENIED        │
     │                        │                       ◀───────────────────────────────│
     │                        │                       │                               │
┌────┴───┐            ┌───────┴───────┐       ┌───────┴───────┐               ┌───────┴───────┐
│ Holder │            │ Wallet Client │       │ Wallet Server │               │ Issuer Server │
└────────┘            └───────────────┘       └───────────────┘               └───────────────┘
  1. Holder, in the Wallet Client Instance selects a Credential to Issue.
  2. The Wallet Client generates a WSK and sends the Signed/Encrypted VerificationData, along with the verification_nonce to the Wallet Server.
  3. The Wallet Server adds any additional necessary VerificationData and calls verification/initiate on the Issuer Server.
  4. The Issuer validates the verification_nonce and the client_encrypted_payload, and returns the PENDING status. The Issuer asynchronously verifies the VerificationData.

    1. Optionally: uses ADDITIONAL_INFO_REQUIRED via verification/notify to obtain more information, which the Wallet Client provides via verification/supplement.
  5. The Issuer updates the Verification Status based on the outcome and sends a notification to the Wallet Server with APPROVED/DENIED.

A.2. Wallet Initiated (Negotiated Verification)

┌────────┐            ┌───────────────┐             ┌───────────────┐               ┌───────────────┐
│ Holder │            │ Wallet Client │             │ Wallet Server │               │ Issuer Server │
└────┬───┘            └───────┬───────┘             └───────┬───────┘               └───────┬───────┘
     │                        │                             │                               │
     │      1. Selects        │                             │                               │
     │  Credential to Issue   │                             │                               │
     │────────────────────────▶                             │                               │
     │                        │                             │                               │
     │                        ├───┐                         │                               │
     │                        │   │ Generates WSK           │                               │
     │                        ◀───┘                         │                               │
     │                        │                             │                               │
     │                        │    2. Initiates session     │                               │
     │                        │╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▶                               │
     │                        │                             │                               │
     │                        │                             │           3. Calls            │
     │                        │                             │    'verification/initiate'    │
     │                        │                             │───────────────────────────────▶
     │                        │                             │                               │
     │                        │                             │                               ├───┐
     │                        │                             │                               │   │ verifies
     │                        │                             │                               ◀───┘ verification_nonce
     │                        │                             │                               │
     │                        │                             │                               │
     │                        │                             │          4. status:           │
     │                        │                             │   ADDITIONAL_INFO_REQUIRED    │
     │                        │                             │   + VerificationDataRequest   │
     │                        │                             ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│
     │                        │                             │                               │
     │                        │         5. Forwards         │                               │
     │                        │  ADDITIONAL_INFO_REQUIRED   │                               │
     │                        ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│                               │
     │                        │                             │                               │
     │      6. Request        │                             │                               │
     │   VerificationData     │                             │                               │
     ◀────────────────────────│                             │                               │
     │                        │                             │                               │
     │      7. Provides       │                             │                               │
     │   VerificationData     │                             │                               │
     │────────────────────────▶                             │                               │
     │                        │                             │                               │
     │                        │          8. Sends           │                               │
     │                        │      Signed/Encrypted       │                               │
     │                        │      VerificationData       │                               │
     │                        │╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▶                               │
     │                        │                             │                               │
     │                        │                             │           9. Calls            │
     │                        │                             │   'verification/supplement'   │
     │                        │                             │───────────────────────────────▶
     │                        │                             │                               │
     │                        │                             │                               ├───┐
     │                        │                             │                               │   │ Decrypts and verifies
     │                        │                             │                               │   │ WSK signature
     │                        │                             │                               ◀───┘
     │                        │                             │                               │
     │                        │                             │                               │
     │                        │                             │                               │
     │                        │                             │      10. status: PENDING      │
     │                        │                             ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│
     │                        │                             │                               │
     │                        │                             │                               ├───┐
     │                        │                             │                               │   │ Asynchronously verifies
     │                        │                             │                               │   │ VerificationData
     │                        │                             │                               ◀───┘
     │                        │                             │                               │
     │                        │                             │                               │
     │                        │                             │                               │
     │                    ┌opt [10.1. Additional Verification]──────────────────────────────────┐
     │                    │   |                             │                               │   │
     │                    │   │                             │    'verification/notify':     │   │
     │                    │   │                             │   ADDITIONAL_INFO_REQUIRED    │   │
     │                    │   │                             ◀───────────────────────────────│   │
     │                    │   │                             │                               │   │
     │                    │   │      Sends additional       │                               │   │
     │                    │   │      Signed/Encrypted       │                               │   │
     │                    │   │      VerificationData       │                               │   │
     │                    │   │╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▶                               │   │
     │                    │   │                             │                               │   │
     │                    │   │                             │  'verification/supplement':   │   │
     │                    │   │                             │          additional           │   │
     │                    │   │                             │       VerificationData        │   │
     │                    │   │                             │───────────────────────────────▶   │
     │                    │   │                             │                               │   │
     │                    └─────────────────────────────────────────────────────────────────────┘
     │                        │                             │                               │
     │                        │                             │                               ├───┐ Updates
     │                        │                             │                               │   │ Verification
     │                        │                             │                               ◀───┘ Status
     │                        │                             │                               │
     │                        │                             │                               │
     │                        │                             │              11.              │
     │                        │                             │    'verification/notify':     │
     │                        │                             │        APPROVED/DENIED        │
     │                        │                             ◀───────────────────────────────│
     │                        │                             │                               │
┌────┴───┐            ┌───────┴───────┐             ┌───────┴───────┐               ┌───────┴───────┐
│ Holder │            │ Wallet Client │             │ Wallet Server │               │ Issuer Server │
└────────┘            └───────────────┘             └───────────────┘               └───────────────┘
  1. Holder, in the Wallet Client Instance, selects a Credential to Issue where the required VerificationData is unknown.
  2. The Wallet Client generates a WSK and initiates a session via the Wallet Server.
  3. The Wallet Server calls verification/initiate on the Issuer Server.
  4. The Issuer validates the verification_nonce and returns a status of ADDITIONAL_INFO_REQUIRED along with a VerificationDataRequest.
  5. The Wallet Server forwards the ADDITIONAL_INFO_REQUIRED status to the Wallet Client.
  6. The Wallet Client requests the VerificationData from the Holder.
  7. The Holder provides the VerificationData.
  8. The Wallet Client sends the Signed and Encrypted VerificationData to the Wallet Server.
  9. The Wallet Server calls verification/supplement on the Issuer Server.
  10. The Issuer decrypts and verifies the WSK signature, returns the PENDING status, and asynchronously verifies the VerificationData.

    1. Optionally: uses ADDITIONAL_INFO_REQUIRED to obtain more information.
  11. The Issuer updates the Verification Status based on the outcome and sends a notification to the Wallet Server.

A.3. Issuer Initiated (Authed Holder)

┌────────┐        ┌────────────────────┐       ┌───────────────┐       ┌───────────────┐               ┌───────────────┐
│ Holder │        │ Issuer App/Website │       │ Wallet Client │       │ Wallet Server │               │ Issuer Server │
└────┬───┘        └──────────┬─────────┘       └───────┬───────┘       └───────┬───────┘               └───────┬───────┘
     │                       │                         │                       │                               │
     │  1. Authenticates &   │                         │                       │                               │
     │    elects to push     │                         │                       │                               │
     │      credentials      │                         │                       │                               │
     │───────────────────────▶                         │                       │                               │
     │                       │                         │                       │                               │
     │                       │        2. push:         │                       │                               │
     │                       │  credential_offer (w/   │                       │                               │
     │                       │     pre-auth code)      │                       │                               │
     │                       │─────────────────────────▶                       │                               │
     │                       │                         │                       │                               │
     │                       │                         ├───┐                   │                               │
     │                       │                         │   │ Generates WSK     │                               │
     │                       │                         ◀───┘                   │                               │
     │                       │                         │                       │                               │
     │                       │                         │       3. Sends        │                               │
     │                       │                         │   Signed/Encrypted    │                               │
     │                       │                         │  VerificationData +   │                               │
     │                       │                         │  verification_nonce   │                               │
     │                       │                         │╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▶                               │
     │                       │                         │                       │                               │
     │                       │                         │                       ├───┐                           │
     │                       │                         │                       │   │ Adds additional           │
     │                       │                         │                       │   │ VerificationData          │
     │                       │                         │                       ◀───┘                           │
     │                       │                         │                       │                               │
     │                       │                         │                       │                               │
     │                       │                         │                       │           4. Calls            │
     │                       │                         │                       │    'verification/initiate'    │
     │                       │                         │                       │───────────────────────────────▶
     │                       │                         │                       │                               │
     │                       │                         │                       │                               ├───┐
     │                       │                         │                       │                               │   │ Validates
     │                       │                         │                       │                               │   │ verification_nonce &
     │                       │                         │                       │                               │   │ payload
     │                       │                         │                       │                               ◀───┘
     │                       │                         │                       │                               │
     │                       │                         │                       │                               │
     │                       │                         │                       │                               │
     │                       │                         │                       │                               ├───┐
     │                       │                         │                       │                               │   │ Verifies pre-auth
     │                       │                         │                       │                               │   │ code
     │                       │                         │                       │                               ◀───┘
     │                       │                         │                       │                               │
     │                       │                         │                       │                               │
     │                       │                     ┌opt [4.1. Additional Verification]─────────────────────────────┐
     │                       │                     │   |                       │                               │   │
     │                       │                     │   │                       │    'verification/notify':     │   │
     │                       │                     │   │                       │   ADDITIONAL_INFO_REQUIRED    │   │
     │                       │                     │   │                       ◀───────────────────────────────│   │
     │                       │                     │   │                       │                               │   │
     │                       │                     │   │   Sends additional    │                               │   │
     │                       │                     │   │   Signed/Encrypted    │                               │   │
     │                       │                     │   │   VerificationData    │                               │   │
     │                       │                     │   │╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▶                               │   │
     │                       │                     │   │                       │                               │   │
     │                       │                     │   │                       │  'verification/supplement':   │   │
     │                       │                     │   │                       │          additional           │   │
     │                       │                     │   │                       │       VerificationData        │   │
     │                       │                     │   │                       │───────────────────────────────▶   │
     │                       │                     │   │                       │                               │   │
     │                       │                     └───────────────────────────────────────────────────────────────┘
     │                       │                         │                       │                               │
     │                       │                         │                       │                               ├───┐
     │                       │                         │                       │                               │   │ Updates Verification
     │                       │                         │                       │                               │   │ Status
     │                       │                         │                       │                               ◀───┘
     │                       │                         │                       │                               │
     │                       │                         │                       │                               │
     │                       │                         │                       │              5.               │
     │                       │                         │                       │    'verification/notify':     │
     │                       │                         │                       │        APPROVED/DENIED        │
     │                       │                         │                       ◀───────────────────────────────│
     │                       │                         │                       │                               │
┌────┴───┐        ┌──────────┴─────────┐       ┌───────┴───────┐       ┌───────┴───────┐               ┌───────┴───────┐
│ Holder │        │ Issuer App/Website │       │ Wallet Client │       │ Wallet Server │               │ Issuer Server │
└────────┘        └────────────────────┘       └───────────────┘       └───────────────┘               └───────────────┘
  1. Holder is authenticated on an Issuer App/Website and elects to push credentials to a Wallet.
  2. The Issuer App/Website pushes the Credential Offer payload containing a pre-authorized_code or similar Pre-auth bearer token to the Wallet Client.
  3. The Wallet Client generates a WSK and sends the Signed/Encrypted VerificationData (including the pre-auth code), along with the verification_nonce to the Wallet Server.
  4. The Wallet Server adds any additional necessary VerificationData and calls verification/initiate on the Issuer Server. The Issuer validates the verification_nonce, payload, and verifies the pre-auth code.

    1. Optionally: uses ADDITIONAL_INFO_REQUIRED via verification/notify to obtain more information (e.g. an OTP).
  5. The Issuer updates the Verification Status based on the outcome and sends an APPROVED/DENIED notification to the Wallet Server.

A.4. Issuer Initiated (Unauthed Holder)

┌────────┐     ┌────────────────────┐   ┌───────────────┐             ┌───────────────┐               ┌───────────────┐
│ Holder │     │ Issuer App/Website │   │ Wallet Client │             │ Wallet Server │               │ Issuer Server │
└────┬───┘     └──────────┬─────────┘   └───────┬───────┘             └───────┬───────┘               └───────┬───────┘
     │                    │                     │                             │                               │
     │   1. Interacts     │                     │                             │                               │
     │  unauthenticated   │                     │                             │                               │
     │────────────────────▶                     │                             │                               │
     │                    │                     │                             │                               │
     │                    │      2. push:       │                             │                               │
     │                    │  credential_offer   │                             │                               │
     │                    │─────────────────────▶                             │                               │
     │                    │                     │                             │                               │
     │                    │                     ├───┐                         │                               │
     │                    │                     │   │ Generates WSK           │                               │
     │                    │                     ◀───┘                         │                               │
     │                    │                     │                             │                               │
     │                    │                     │    3. Initiates session     │                               │
     │                    │                     │╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▶                               │
     │                    │                     │                             │                               │
     │                    │                     │                             │           4. Calls            │
     │                    │                     │                             │    'verification/initiate'    │
     │                    │                     │                             │───────────────────────────────▶
     │                    │                     │                             │                               │
     │                    │                     │                             │                               ├───┐
     │                    │                     │                             │                               │   │ Validates
     │                    │                     │                             │                               ◀───┘
     │                    │                     │                             │                               │
     │                    │                     │                             │                               │
     │                    │                     │                             │          5. status:           │
     │                    │                     │                             │   ADDITIONAL_INFO_REQUIRED    │
     │                    │                     │                             │   + VerificationDataRequest   │
     │                    │                     │                             ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│
     │                    │                     │                             │                               │
     │                    │                     │         6. Forwards         │                               │
     │                    │                     │  ADDITIONAL_INFO_REQUIRED   │                               │
     │                    │                     │          (proofing          │                               │
     │                    │                     │        requirements)        │                               │
     │                    │                     ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│                               │
     │                    │                     │                             │                               │
     │               7. Requests                │                             │                               │
     │            VerificationData              │                             │                               │
     ◀──────────────────────────────────────────│                             │                               │
     │                    │                     │                             │                               │
     │               8. Provides                │                             │                               │
     │            VerificationData              │                             │                               │
     │──────────────────────────────────────────▶                             │                               │
     │                    │                     │                             │                               │
     │                    │                     │          9. Sends           │                               │
     │                    │                     │      Signed/Encrypted       │                               │
     │                    │                     │      VerificationData       │                               │
     │                    │                     │╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▶                               │
     │                    │                     │                             │                               │
     │                    │                     │                             │           10. Calls           │
     │                    │                     │                             │   'verification/supplement'   │
     │                    │                     │                             │───────────────────────────────▶
     │                    │                     │                             │                               │
     │                    │                     │                             │                               ├───┐
     │                    │                     │                             │                               │   │ Decrypts and
     │                    │                     │                             │                               ◀───┘ verifies WSK
     │                    │                     │                             │                               │     signature
     │                    │                     │                             │                               │
     │                    │                     │                             │                               │
     │                    │                     │                             │      11. status: PENDING      │
     │                    │                     │                             ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│
     │                    │                     │                             │                               │
     │                    │                     │                             │                               ├───┐
     │                    │                     │                             │                               │   │ Asynchronously
     │                    │                     │                             │                               ◀───┘ evaluates
     │                    │                     │                             │                               │     VerificationData
     │                    │                     │                             │                               │
     │                    │                     │                             │                               │
     │                    │                 ┌opt [11.1. Additional Verification]──────────────────────────────────┐
     │                    │                 │   |                             │                               │   │
     │                    │                 │   │                             │    'verification/notify':     │   │
     │                    │                 │   │                             │   ADDITIONAL_INFO_REQUIRED    │   │
     │                    │                 │   │                             ◀───────────────────────────────│   │
     │                    │                 │   │                             │                               │   │
     │                    │                 │   │      Sends additional       │                               │   │
     │                    │                 │   │      Signed/Encrypted       │                               │   │
     │                    │                 │   │      VerificationData       │                               │   │
     │                    │                 │   │╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▶                               │   │
     │                    │                 │   │                             │                               │   │
     │                    │                 │   │                             │  'verification/supplement':   │   │
     │                    │                 │   │                             │          additional           │   │
     │                    │                 │   │                             │       VerificationData        │   │
     │                    │                 │   │                             │───────────────────────────────▶   │
     │                    │                 │   │                             │                               │   │
     │                    │                 └─────────────────────────────────────────────────────────────────────┘
     │                    │                     │                             │                               │
     │                    │                     │                             │                               ├───┐
     │                    │                     │                             │                               │   │ Updates
     │                    │                     │                             │                               │   │ Verification
     │                    │                     │                             │                               ◀───┘ Status
     │                    │                     │                             │                               │
     │                    │                     │                             │              12.              │
     │                    │                     │                             │    'verification/notify':     │
     │                    │                     │                             │        APPROVED/DENIED        │
     │                    │                     │                             ◀───────────────────────────────│
     │                    │                     │                             │                               │
┌────┴───┐     ┌──────────┴─────────┐   ┌───────┴───────┐             ┌───────┴───────┐               ┌───────┴───────┐
│ Holder │     │ Issuer App/Website │   │ Wallet Client │             │ Wallet Server │               │ Issuer Server │
└────────┘     └────────────────────┘   └───────────────┘             └───────────────┘               └───────────────┘
  1. Holder interacts with an Issuer App/Website but is not authenticated.
  2. The Issuer App/Website pushes the Credential Offer payload to the Wallet Client.
  3. The Wallet Client generates a WSK and initiates a session via the Wallet Server.
  4. The Wallet Server calls verification/initiate on the Issuer Server.
  5. The Issuer validates the verification_nonce and returns a status of ADDITIONAL_INFO_REQUIRED along with a VerificationDataRequest.
  6. The Wallet Server forwards the ADDITIONAL_INFO_REQUIRED status with the proofing requirements to the Wallet Client.
  7. The Wallet Client requests the VerificationData from the Holder.
  8. The Holder provides the VerificationData.
  9. The Wallet Client sends the Signed/Encrypted VerificationData to the Wallet Server.
  10. The Wallet Server calls verification/supplement on the Issuer Server.
  11. The Issuer decrypts and verifies the WSK signature, returns the PENDING status, and asynchronously verifies the VerificationData.

    1. Optionally: uses ADDITIONAL_INFO_REQUIRED to obtain more information.
  12. The Issuer updates the Verification Status based on the outcome and sends an APPROVED/DENIED notification to the Wallet Server.

A.5. Device Migration

┌────────┐      ┌───────────────────┐   ┌───────────────┐               ┌───────────────┐
│ Holder │      │ New Wallet Client │   │ Wallet Server │               │ Issuer Server │
└────┬───┘      └─────────┬─────────┘   └───────┬───────┘               └───────┬───────┘
     │                    │                     │                               │
     │  1. Sets up new    │                     │                               │
     │  Wallet Client &   │                     │                               │
     │     migrates       │                     │                               │
     │────────────────────▶                     │                               │
     │                    │                     │                               │
     │                    ├───┐                 │                               │
     │                    │   │ Generates WSK   │                               │
     │                    ◀───┘                 │                               │
     │                    │                     │                               │
     │                    │                     ├───┐                           │
     │                    │                     │   │ Identifies previous Wallet Id
     │                    │                     ◀───┘                           │
     │                    │                     │                               │
     │                    │                     │                               │
     │                    │                     │              2.               │
     │                    │                     │   'verification/initiate':    │
     │                    │                     │      (old Wallet Id, new      │
     │                    │                     │      Wallet Id, new WSK)      │
     │                    │                     │───────────────────────────────▶
     │                    │                     │                               │
     │                    │                     │                               ├───┐
     │                    │                     │                               │   │ Verifies relationship
     │                    │                     │                               ◀───┘  between instances
     │                    │                     │                               │
     │                    │                     │                               │
     │                    │                     │                               │
     │                ┌opt [2.1. Additional─────────────────────────────────────────┐
     │                │Verification]            │                               │   │
     │                │   │                     │    'verification/notify':     │   │
     │                │   │                     │   ADDITIONAL_INFO_REQUIRED    │   │
     │                │   │                     ◀───────────────────────────────│   │
     │                │   │                     │                               │   │
     │                │   │  Sends additional   │                               │   │
     │                │   │  Signed/Encrypted   │                               │   │
     │                │   │  VerificationData   │                               │   │
     │                │   │╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▶                               │   │
     │                │   │                     │                               │   │
     │                │   │                     │  'verification/supplement':   │   │
     │                │   │                     │          additional           │   │
     │                │   │                     │       VerificationData        │   │
     │                │   │                     │───────────────────────────────▶   │
     │                │   │                     │                               │   │
     │                └─────────────────────────────────────────────────────────────┘
     │                    │                     │                               │
     │                    │                     │                               ├───┐
     │                    │                     │                               │   │ Approves new
     │                    │                     │                               ◀───┘ verification
     │                    │                     │                               │
     │                    │                     │                               │
     │                    │                     │              3.               │
     │                    │                     │    'verification/notify':     │
     │                    │                     │           APPROVED            │
     │                    │                     ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│
     │                    │                     │                               │
┌────┴───┐      ┌─────────┴─────────┐   ┌───────┴───────┐               ┌───────┴───────┐
│ Holder │      │ New Wallet Client │   │ Wallet Server │               │ Issuer Server │
└────────┘      └───────────────────┘   └───────────────┘               └───────────────┘
  1. Holder sets up a new Wallet Client Instance and wishes to migrate credentials from a previous instance. The Wallet Client generates a new WSK.
  2. The Wallet Server identifies the previous Wallet Id and calls 'verification/initiate' with the old Wallet Id, new Wallet Id, and new WSK. The Issuer verifies the relationship between the instances.

    1. Optionally: uses ADDITIONAL_INFO_REQUIRED to obtain more information from the Holder.
  3. The Issuer approves the new verification session and sends a notification with APPROVED.

Appendix B. Acknowledgements

We would like to thank Christian Bormann, George Fletcher, Martijn Haring, Hicham Lozi, Dima Postnikov, Kristina Yasuda, Rajvardhan S Deshmukh, David Zeuthen for their valuable feedback and contributions to this specification.

Appendix C. Notices

Copyright (c) 2026 The OpenID Foundation.

The OpenID Foundation (OIDF) grants to any Contributor, developer, implementer, or other interested party a non-exclusive, royalty free, worldwide copyright license to reproduce, prepare derivative works from, distribute, perform and display, this Implementers Draft, Final Specification, or Final Specification Incorporating Errata Corrections solely for the purposes of (i) developing specifications, and (ii) implementing Implementers Drafts, Final Specifications, and Final Specification Incorporating Errata Corrections based on such documents, provided that attribution be made to the OIDF as the source of the material, but that such attribution does not indicate an endorsement by the OIDF.

The technology described in this specification was made available from contributions from various sources, including members of the OpenID Foundation and others. Although the OpenID Foundation has taken steps to help ensure that the technology is available for distribution, it takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this specification or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any independent effort to identify any such rights. The OpenID Foundation and the contributors to this specification make no (and hereby expressly disclaim any) warranties (express, implied, or otherwise), including implied warranties of merchantability, non-infringement, fitness for a particular purpose, or title, related to this specification, and the entire risk as to implementing this specification is assumed by the implementer. The OpenID Intellectual Property Rights policy (found at openid.net) requires contributors to offer a patent promise not to assert certain patent claims against other contributors and against implementers. OpenID invites any interested party to bring to its attention any copyrights, patents, patent applications, or other proprietary rights that may cover technology that may be required to practice this specification.

Appendix D. Document History

[[ To be removed from the final specification ]]

-01

Author's Address

Gareth Oliver
Google