| oid4vcis2s | September 2026 | |
| Oliver | Standards Track | [Page] |
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).¶
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.¶
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.¶
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.¶
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:¶
The Wallet Client Instance generates a WSK, and the Wallet Server initiates the Verification on the Issuer Server.¶
The Wallet Client Instance collects Verification Data and signs-then-encrypts it using the WSK and the Issuer Encryption Key.¶
The Wallet Server calls The Issuer Server, passing Wallet Client-supplied Verification Data and, optionally, providing additional Wallet Server-supplied Verification Data.¶
The Issuer Server decrypts and verifies the Verification Data using the WSK, and evaluates it along with any Wallet Server provided Verification Data.¶
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:¶
The Wallet Server retrieves a batch of Credentials using the Credential Instance Identifiers and the client payload.¶
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.¶
This process is repeated to refresh the Credentials and to update them. Post initial issuance, Credentials lifecycle can be managed through the following processes:¶
This specification defines a series of endpoints on both the Wallet Server and the Issuer Server. Endpoints.¶
| 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 instance IDs after verification approval. |
| Get Credential | /credential/get | Issuer | Retrieves the verifiable credentials for a particular credential instance. |
| 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 instance. |
| Credential Management | /credential/manage | Both | Handles ongoing management and lifecycle operations for a Credential Instance. |
| Event Notification | /event/notify | Both | Bidirectional poke channel for action-based notifications. |
The following requirements apply to all endpoints.¶
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 SessionId with the mTLS client identity that created it and reject requests for that SessionId from any other identity.¶
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¶
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).¶
| Header | Direction | Type | Description |
|---|---|---|---|
| Api-Version | Request | String (semantic version) | Required. Semantic version requested by the client (e.g., 1.0.0) |
| Api-Version | Response | String (semantic version) | Required. The version used to process the request |
| Api-Supported-Versions | Response | String (comma-separated versions) | Comma-separated list of versions the server supports |
| Sunset | Response | 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.¶
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:¶
| 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., errorCode for machine-readable application codes, retryable flag, validationErrors array for field-level issues). See Section 3.1 of [RFC9457] for more information.¶
This specification defines the following error types:¶
All application-layer encryption is performed using JWE [RFC7516] with HPKE [RFC9180] key encapsulation, as defined in [I-D.ietf-jose-hpke-encrypt].¶
The JweEncryptedPayload is the data structure used to represent an encrypted payload in the API.¶
| 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).¶
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:¶
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.¶
All keys are communicated between the Wallet and Issuer using this common key structure.¶
| Field | Type | Description |
|---|---|---|
| keyType | 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 publicKey MUST include the alg identifier and is RECOMMENDED to include a keyId.¶
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¶
This section details how large content can be passed by reference to a downloadable URL, rather than by value.¶
| Field | Type | Description |
|---|---|---|
| downloadUrl | string (URI) | REQUIRED: The URL where the content can be downloaded. |
| contentDigest | string (byte) | REQUIRED: SHA-256 digest of the JWE content. |
| contentSize | integer | OPTIONAL: The size of the content in bytes. |
| expiresAt | string (date-time) | OPTIONAL: The timestamp after which the URL expires. |
| extensions | object | OPTIONAL: Implementation-specific extension fields. |
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.¶
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).¶
The API uses the following identifiers:¶
All identifiers are opaque strings assigned by the issuer unless otherwise noted. 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.¶
SessionId MUST be globally unique. CredentialInstanceId MUST be unique for an Issuer. VerificationId and CredentialInstanceIds MUST be unique for a given SessionId.¶
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).¶
There are five different flows we are considering in this specification:¶
push one or more credentials to a Wallet Client Instance of their choosing.¶
All engagement is modeled as the Wallet receiving a Credential Offer payload from the Issuer.¶
This could be obtained:¶
Via a back-channel call from the Issuer Server to the Wallet Server¶
TODO: Determine the best way to pass Pre-Auth/VerificationDataRequest/Issuer State, whether to re-use what is in canonical VCI or extend it¶
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.¶
The Wallet Server provides a long-lived SessionId to associate with the WalletSigningKey. The Issuer provides the VerificationId in the response, which is used for follow-up calls to the Verification Endpoints.¶
CredentialInstanceIdentifiers are retrieved after verification through the Credential Provision endpoint.¶
This endpoint is protected against replay attacks through a signed nonce mechanism. The wallet produces a digital signature over the sessionId using the walletSigningKey and includes this signature as the verificationNonce field in the request.¶
Issuers MUST perform the following verification steps:¶
Because each sessionId is a unique UUID generated per verification session, a replayed request will be rejected — either the sessionId was already consumed, or a different sessionId will not match the original signature. Replay from a different device is also prevented, as only the holder of the private walletSigningKey can produce a valid signature.¶
| Field | Type | Description |
|---|---|---|
| sessionId | string(UUID) | REQUIRED: Wallet Server-generated UUID for this session. Shared correlation identifier that threads verification and credential issuance. |
| credentialConfigurationIds | Array (string) | REQUIRED: Identifies the credential types/templates for the credentials being requested.Issuers use this to determine which credential type and configuration apply. |
| walletSigningKeyData | 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 sessionId and used to verify this and subsequent requests originate from the same authenticated client instance. |
| verificationNonce | string(bytes) | REQUIRED: Signature over sessionId, providing replay protection and cryptographic binding to the session. |
| verificationData | Object (VerificationDataResponse) | OPTIONAL: VerificationDataResponse to allow for Wallets to combine providing evidence when it is known in advance. |
| supportedVerificationTypes | Array(String) |
OPTIONAL: List of verificationTypes this Wallet Client Instance supports, that can be used with ADDITIONAL_INFO_REQUIRED
|
| requestedDeviceCount | 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 authorizedDeviceCount 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. |
The Response Body schema contains all of the fields in the VerificationStatus schema.¶
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.¶
| Field | Type | Description |
|---|---|---|
| sessionId | string(UUID) |
REQUIRED: Wallet-Generated id received in the initiate call. |
| verificationId | string(UUID) | REQUIRED: Issuer-generated id for the current verification session. |
| verificationDataPayload | Object (VerificationDataResponse) | REQUIRED: Containing verification data for this verification session. |
| extensions | Object | OPTIONAL: Implementation-specific extension fields. |
The Response Body schema contains all of the fields in the VerificationStatus schema.¶
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.¶
The Request Body contains allOf the fields in the VerificationStatus schema.¶
| Field | Type | Description |
|---|---|---|
| sessionId | string(UUID) |
REQUIRED: Wallet-Generated id received in the initiate call. |
| verificationId | string(UUID) | REQUIRED: Issuer-generated id for the current verification session. |
The path MUST be /verification/status. This endpoint is hosted by the Issuer Server only.¶
| Field | Type | Description |
|---|---|---|
| sessionId | string(UUID) |
REQUIRED: Wallet-Generated id received in the initiate call. |
| verificationId | string(UUID) | REQUIRED: Issuer-generated id for the current verification session. |
| extensions | Object | OPTIONAL: Implementation-specific extension fields. |
The Response Body contains allOf the fields in the VerificationStatus schema.¶
The path MUST be /verification/cancel. This endpoint is hosted by the Issuer Server only.¶
| Field | Type | Description |
|---|---|---|
| sessionId | string(UUID) |
REQUIRED: Wallet-Generated id received in the initiate call. |
| verificationId | 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. |
| Field | Type | Description |
|---|---|---|
| sessionId | string(UUID) |
REQUIRED: Wallet-Generated id received in the initiate call. |
| verificationId | string(UUID) | REQUIRED: Issuer-generated id for the current session. |
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:¶
| Field | Type | Description |
|---|---|---|
| sessionId | string(UUID) |
REQUIRED: Wallet-Generated id received in the initiate call. |
| verificationId | 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:¶
| Status | Description | Next Step |
|---|---|---|
| "APPROVED" | Verification Passed | Wallet Server calls /credential/provision to fetch the credentialInstanceIds |
| "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:¶
| Field | Type | Description |
|---|---|---|
| credentialConfigurationIds | Array (string) | REQUIRED: Credential Configurations that |
| authorizedDeviceCount | Integer (>=1), default=1 | OPTIONAL: Maximum number of devices this SessionId/VerificationId can be used on, after which the Issuer SHOULD reject any further attempts. |
| Field | Type | Description |
|---|---|---|
| reasonCode | string | REQUIRED: Rejection reason code. |
| rejectedDetails | string | OPTIONAL: Details for logging. |
| Field | Type | Description |
|---|---|---|
| reasonCode | string | REQUIRED: Denial reason code. |
| deniedMessage | string | REQUIRED: Message for the human. |
| Field | Type | Description |
|---|---|---|
| verificationDataRequest | Object (VerificationDataRequest) | REQUIRED: Used to collect additional information from the holder. |
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:¶
Pre-auth bearer token binding this session to another¶
The flow is as follows:¶
supported_verification_types¶
Issuer Server provides a VerificationDataRequest detailing the requested Data¶
| Field | Type | Description |
|---|---|---|
| verificationDataItems | Array (VerificationDataItemRequest) | REQUIRED: Array of items requested |
| deadline | string (date-time) | OPTIONAL: deadline for the request, after which the Verification will be DENIED. |
| maxAttempts | integer | OPTIONAL: Maximum number of attempts allowed, after which the Verification will be DENIED. |
| extensions | object | OPTIONAL: Implementation-specific extension fields |
| 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.¶
| Field | Type | Description |
|---|---|---|
| clientEncryptedPayload | Array (JweEncryptedPayload (VerificationDataItem)) | OPTIONAL: Encrypted payload originating from the Wallet Client, containing a VerificationDataItem. |
| serverVerificationDataItem | Array (VerificationDataItem) | OPTIONAL: Verification items provided by the Wallet Server. |
| additionalAssessments | Array (object) | OPTIONAL: Additional risk or eligibility assessments from the Wallet Server. |
| extensions | object | OPTIONAL: Implementation-specific extension fields. |
clientEncryptedPayload contains the WALLET_CLIENT originating VerificationDataItem, while serverVerificationDataItem 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 clientEncryptedPayload using the WalletSigningKey in the active session before proceeding to evaluate the VerificationDataItem.¶
| 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.¶
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.¶
This endpoint is used to fetch credential instance IDs after verification approval. The path MUST be /credential/provision.¶
| Field | Type | Description |
|---|---|---|
| sessionId | string (UUID) | REQUIRED: Wallet Server-generated UUID for this session. |
| verificationId | string (UUID) | REQUIRED: Issuer-generated id for the current session. |
| extensions | object | OPTIONAL: Implementation-specific extension fields. |
| Field | Type | Description |
|---|---|---|
| CredentialInstances | Array (object) | REQUIRED: Array of objects containing credential configuration and instance IDs. |
| extensions | object | OPTIONAL: Implementation-specific extension fields. |
Each CredentialInstances object contains:¶
This endpoint is used to retrieve the verifiable credentials for a specific credential instance. The path MUST be /credential/get.¶
| Field | Type | Description |
|---|---|---|
| sessionId | string | REQUIRED: Identifier for the overarching Session. |
| credentialInstanceId | string | REQUIRED: Credential Identifier. |
| reason | string | REQUIRED.: Reason for the Wallet initiating the credential fetch, for debugging purposes. |
| walletEncryptionKey | object (KeyData) | REQUIRED: Key provided for the Issuer to encrypt sensitive data to. |
| clientEncryptedData | object (ClientEncryptedPayload) | OPTIONAL: Payload containing an object containing an array of presentmentKeys. |
| currentCredentialMetadataVersion | string | OPTIONAL: Current Version identifier for the credential metadata. |
| extensions | object | OPTIONAL: Implementation-specific extension fields. |
| Field | Type | Description |
|---|---|---|
| credentialMetadata | object (CredentialMetadata) | OPTIONAL: Metadata for the specific credential configuration. |
| credentialVersion | 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. |
This endpoint retrieves metadata for a specific credential configuration. The path MUST be /credential/metadata.¶
| Field | Type | Description |
|---|---|---|
| sessionId | string | REQUIRED: Identifier for the overarching Session. |
| credentialInstanceId | string | REQUIRED: Credential Identifier. |
| walletEncryptionKey | object (KeyData) | REQUIRED: Key provided for the Issuer to encrypt sensitive data to. |
| credentialMetadataVersion | string | OPTIONAL: Version identifier for the requested metadata. |
| extensions | object | OPTIONAL: Implementation-specific extension fields. |
| Field | Type | Description |
|---|---|---|
| credentialMetadata | object (CredentialMetadata) | OPTIONAL: Metadata for the specific credential instance. Includes displayData as well as other relevant metadata. |
| extensions | object | OPTIONAL: Implementation-specific extension fields. |
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.¶
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?).¶
| Field | Type | Description |
|---|---|---|
| sessionId | string | REQUIRED: Identifier for the overarching Session being queried. |
| credentialInstanceId | string | REQUIRED: Credential Identifier whose status is being queried. |
| extensions | object | OPTIONAL: Implementation specific extensions |
| Field | Type | Description |
|---|---|---|
| currentStatus | String (CredentialStatus) | REQUIRED: The current status of the credential instance |
| currentVersion | String | REQUIRED: Unique identifier for the credential data set version. |
| lastStatusChangeTime | String (HTTP-date) | OPTIONAL: Date and time when the status was last updated |
| lastStatusChangeReason | 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.¶
| 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 |
This bi-directrional endpoint instructs the hosting party to perform an action for a particular credentialInstanceId. The path MUST be /credential/manage.¶
| Field | Type | Description |
|---|---|---|
| sessionId | string (UUID) | REQUIRED: Wallet Server-generated UUID for this session. |
| credentialInstanceId | string | REQUIRED: Credential Identifier 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. |
| reasonDetail | 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. |
| Field | Type | Description |
|---|---|---|
| sessionId | string (UUID) | REQUIRED: Wallet Server-generated UUID for this session. |
| credentialInstanceId | string | REQUIRED: Credential Identifier associated with this management operation. |
| currentStatus | string (CredentialStatus) | REQUIRED: The status of the credential instance after the operation. |
| previousStatus | string (CredentialStatus) | OPTIONAL: The status of the credential instance before the operation was initiated. |
| outcome | string (Enum) |
REQUIRED: The outcome of the operation. One of: COMPLETED, SCHEDULED, FAILED, NO_CHANGE. |
| failureReason | string |
OPTIONAL: Machine-readable reason for failure if the outcome is failed. |
| extensions | object | OPTIONAL: Implementation-specific extension fields. |
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.¶
| Field | Type | Description |
|---|---|---|
| sessionId | string | REQUIRED: Identifier for the overarching Session. |
| credentialInstanceId | string | REQUIRED: Credential Identifier associated with the event. |
| eventType | string | REQUIRED: The type of event being notified. |
| triggeringRequestId | string (UUID) | OPTIONAL: The x-request-id of the original request that triggered this event. |
| eventTimestamp | string (date-time) | REQUIRED: The timestamp when the event was created. |
| eventDetails | object | TYPE DEPENDENT: Implementation-specific details dependent on the eventType. |
| extensions | object | OPTIONAL: Implementation-specific extension fields. |
The following event types are defined by this specification:¶
| 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¶
The response body schema optionally contains an acknowledged boolean to indicate that the event was processed.¶
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.¶
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.¶
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.¶
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.¶
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.¶
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.¶
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¶
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 + │ │
│ │ verificationNonce │ │
│ │╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▶ │
│ │ │ │
│ │ ├───┐ │
│ │ │ │ Adds additional │
│ │ │ │ VerificationData │
│ │ ◀───┘ │
│ │ │ │
│ │ │ │
│ │ │ 3. Calls │
│ │ │ 'verification/initiate' │
│ │ │───────────────────────────────▶
│ │ │ │
│ │ │ ├───┐
│ │ │ │ │ Validates
│ │ │ │ │ verificationNonce &
│ │ │ │ │ encryptedClientPayload
│ │ │ ◀───┘
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ 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 │
└────────┘ └───────────────┘ └───────────────┘ └───────────────┘
¶
verification/initiate on the Issuer Server.¶
The Issuer validates the verificationNonce and the encryptedClientPayload, and returns the PENDING status. The Issuer asynchronously verifies the VerificationData.¶
verification/notify to obtain more information, which the Wallet Client provides via verification/supplement.¶
┌────────┐ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Holder │ │ Wallet Client │ │ Wallet Server │ │ Issuer Server │
└────┬───┘ └───────┬───────┘ └───────┬───────┘ └───────┬───────┘
│ │ │ │
│ 1. Selects │ │ │
│ Credential to Issue │ │ │
│────────────────────────▶ │ │
│ │ │ │
│ ├───┐ │ │
│ │ │ Generates WSK │ │
│ ◀───┘ │ │
│ │ │ │
│ │ 2. Initiates session │ │
│ │╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▶ │
│ │ │ │
│ │ │ 3. Calls │
│ │ │ 'verification/initiate' │
│ │ │───────────────────────────────▶
│ │ │ │
│ │ │ ├───┐
│ │ │ │ │ verifies
│ │ │ ◀───┘ verificationNonce
│ │ │ │
│ │ │ │
│ │ │ 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 │
└────────┘ └───────────────┘ └───────────────┘ └───────────────┘
¶
verification/initiate on the Issuer Server.¶
ADDITIONAL_INFO_REQUIRED along with a VerificationDataRequest.¶
ADDITIONAL_INFO_REQUIRED status to the Wallet Client.¶
verification/supplement on the Issuer Server.¶
The Issuer decrypts and verifies the WSK signature, returns the PENDING status, and asynchronously verifies the VerificationData.¶
┌────────┐ ┌────────────────────┐ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ 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 + │ │
│ │ │ verificationNonce │ │
│ │ │╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌▶ │
│ │ │ │ │
│ │ │ ├───┐ │
│ │ │ │ │ Adds additional │
│ │ │ │ │ VerificationData │
│ │ │ ◀───┘ │
│ │ │ │ │
│ │ │ │ │
│ │ │ │ 4. Calls │
│ │ │ │ 'verification/initiate' │
│ │ │ │───────────────────────────────▶
│ │ │ │ │
│ │ │ │ ├───┐
│ │ │ │ │ │ Validates
│ │ │ │ │ │ verificationNonce &
│ │ │ │ │ │ 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 │
└────────┘ └────────────────────┘ └───────────────┘ └───────────────┘ └───────────────┘
¶
pre-authorized_code or similar Pre-auth bearer token to the Wallet Client.¶
The Wallet Server adds any additional necessary VerificationData and calls verification/initiate on the Issuer Server. The Issuer validates the verificationNonce, payload, and verifies the pre-auth code.¶
verification/notify to obtain more information (e.g. an OTP).¶
┌────────┐ ┌────────────────────┐ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ 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 │
└────────┘ └────────────────────┘ └───────────────┘ └───────────────┘ └───────────────┘
¶
verification/initiate on the Issuer Server.¶
ADDITIONAL_INFO_REQUIRED along with a VerificationDataRequest.¶
ADDITIONAL_INFO_REQUIRED status with the proofing requirements to the Wallet Client.¶
verification/supplement on the Issuer Server.¶
The Issuer decrypts and verifies the WSK signature, returns the PENDING status, and asynchronously verifies the VerificationData.¶
┌────────┐ ┌───────────────────┐ ┌───────────────┐ ┌───────────────┐
│ Holder │ │ New Wallet Client │ │ Wallet Server │ │ Issuer Server │
└────┬───┘ └─────────┬─────────┘ └───────┬───────┘ └───────┬───────┘
│ │ │ │
│ 1. Sets up new │ │ │
│ Wallet Client & │ │ │
│ migrates │ │ │
│────────────────────▶ │ │
│ │ │ │
│ ├───┐ │ │
│ │ │ Generates WSK │ │
│ ◀───┘ │ │
│ │ │ │
│ │ ├───┐ │
│ │ │ │ Identifies previous SessionId
│ │ ◀───┘ │
│ │ │ │
│ │ │ │
│ │ │ 2. │
│ │ │ 'verification/initiate': │
│ │ │ (old SessionId, new │
│ │ │ SessionId, 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 │
└────────┘ └───────────────────┘ └───────────────┘ └───────────────┘
¶
The Wallet Server identifies the previous SessionId and calls 'verification/initiate' with the old SessionId, new SessionId, and new WSK. The Issuer verifies the relationship between the instances.¶
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.¶
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.¶
[[ To be removed from the final specification ]]¶
-01¶