Accept SD-JWT Verifiable Credentials via OID4VCI
In this guide, we take a look at how you can use the walt.id Enterprise wallet service API to accept an SD-JWT Verifiable Credential from an issuer via OID4VCI.
Ensure you have set up a wallet (service) and linked the necessary enterprise services (e.g., Credential Store) before proceeding with this guide.
Credential Offer URL
A credential offer URL is a standardized method, as per the OID4VCI specification, to communicate the issuance of
credentials between issuer and wallet. This URL can take various forms, such as a QR code or a link, and generally
begins with openid-credential-offer://.
Example Offer URL
openid-credential-offer://issuer.portal.walt.id/?credential_offer=<credential_offer>
Example of a Credential Offer Object for SD-JWT VCs
{
"credential_issuer": "https://issuer.demo.walt.id",
"credential_configuration_ids": [
"identity_credential_vc+sd-jwt"
]
"grants": {
"authorization_code": {
"issuer_state": "<issuer_state>"
},
"urn:ietf:params:oauth:grant-type:pre-authorized_code": {
"pre-authorized_code": "<pre-authorized_code>",
"user_pin_required": false
}
}
}
Accepting SD-JWT Credential Offers
SD-JWT credentials have built-in selective disclosure capabilities, allowing the holder to choose which claims to share when presenting the credential.
Endpoint: /v1/{target}/wallet-service-api/credentials/receive | API Reference
Example Request
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v1/{target}/wallet-service-api/credentials/receive' \
-H 'accept: */*' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"offerUrl": "openid-credential-offer://issuer.example.org/issue/?credential_offer_uri=https%3A%2F%2Fissuer.example.org%2FcredentialOffer%3Fabc123xyz789",
"keyReference": "example.kms.key1",
"didReference": "example.didstore.did1"
}'
Path Parameters
orgID: - When performing operations within an organization, it is essential to use the organization's Base URL or another valid host alias. For example, if your organization is namedtest, your default Base URL will betest.enterprise-sandbox.walt.devwhen using the sandbox environment.target: resourceIdentifier - The target indicates the organization + tenant + wallet which should be used to receive the credential ({organizationID}.{tenantID}.[walletID]), e.g.waltid.tenant1.wallet1
Body Parameters
offerUrlString - An OID4VCI offer URL.keyReference(optional) String - The resource ID (target) of the key to which the received credential should be bound.didReference(optional) String - The DID reference of a DID stored in a linked DID Store.key(optional) Object - A key object or reference key object for external KMS.did(optional) String - DID as a string.metadata(optional) Object - Arbitrary JSON object that will be stored together with the credential.runPolicies(optional) Boolean - If set totrue, the wallet service will run any holder policies.
Response Codes
201- SD-JWT Credential received successfully.
Body
{
"offeredCredential": {
"format": "vc+sd-jwt",
"vct": "http://org.enterprise.localhost:3000/v1/org.tenant.issuer2/issuer-service-api/openid4vc/draft13/identity_credential",
"credential_definition": {},
"cryptographic_binding_methods_supported": [
"jwk"
]
},
"credentialResponse": {
"format": "vc+sd-jwt",
"credential": "eyJraWQiOiJkaWQ6a2V5OnptWWc5YmdLbVJpQ3FUVGQ5TUExdWZWRTl0ZnpVcHR3UXA0R01SeHB0WHF1Sld3NFVqNWRCUVY3QlBQQm5oSEd6RGF3UlJxSmltdnM3c1FZMUVOWTJ3SEdaU2RBN3BQQWhvYThqV0pYR3JaWHNVSFdMI3ptWWc5YmdLbVJpQ3FUVGQ5TUExdWZWRTl0ZnpVcHR3UXA0R01SeHB0WHF1Sld3NFVqNWRCUVY3QlBQQm5oSEd6RGF3UlJxSmltdnM3c1FZMUVOWTJ3SEdaU2RBN3BQQWhvYThqV0pYR3JaWHNVSFdMIiwidHlwIjoidmMrc2Qtand0IiwiYWxnIjoiRWREU0EifQ.eyJnaXZlbl9uYW1lIjoiSm9obiIsImZhbWlseV9uYW1lIjoiRG9lIiwiZW1haWwiOiJqb2huZG9lQGV4YW1wbGUuY29tIiwicGhvbmVfbnVtYmVyIjoiKzEtMjAyLTU1NS0wMTAxIiwiYWRkcmVzcyI6eyJzdHJlZXRfYWRkcmVzcyI6IjEyMyBNYWluIFN0IiwibG9jYWxpdHkiOiJBbnl0b3duIiwicmVnaW9uIjoiQW55c3RhdGUiLCJjb3VudHJ5IjoiVVMifSwiaXNfb3Zlcl8xOCI6dHJ1ZSwiaXNfb3Zlcl8yMSI6dHJ1ZSwiaXNfb3Zlcl82NSI6dHJ1ZSwiaWQiOiJ1cm46dXVpZDplMzUxY2VhZi0zYWIwLTRkYTQtYjY2NC0zNmFjNjk0YzI0NWEiLCJpYXQiOjE3NjEzMTgzODksIm5iZiI6MTc2MTMxODM4OSwiZXhwIjoxNzkyODU0Mzg5LCJfc2RfYWxnIjoic2hhLTI1NiIsImlzcyI6ImRpZDprZXk6em1ZZzliZ0ttUmlDcVRUZDlNQTF1ZlZFOXRmelVwdHdRcDRHTVJ4cHRYcXVKV3c0VWo1ZEJRVjdCUFBCbmhIR3pEYXdSUnFKaW12czdzUVkxRU5ZMndIR1pTZEE3cFBBaG9hOGpXSlhHclpYc1VIV0wiLCJjbmYiOnsia2lkIjoiZGlkOmp3azpleUpyZEhraU9pSlBTMUFpTENKamNuWWlPaUpGWkRJMU5URTVJaXdpYTJsa0lqb2lVVFExVWtvNVdIcGxiM0pqVTFaamVpMVdaRmhQV0VSMmJFaDNkMkpaZDJWWlREQjRkR0ZrZWs5Vk9DSXNJbmdpT2lKTVVXVTRhVzlqUlhkWWIzRkNVSFI1VWt0NVFteEpPR3BUTkVoeGFUZG1Sa2s1UjFwRFVDMW1VbDlySW4wIn0sInZjdCI6Imh0dHA6Ly9vcmcuZW50ZXJwcmlzZS5sb2NhbGhvc3Q6MzAwMC92MS9vcmcudGVuYW50Lmlzc3VlcjIvaXNzdWVyLXNlcnZpY2UtYXBpL29wZW5pZDR2Yy9kcmFmdDEzL2lkZW50aXR5X2NyZWRlbnRpYWwiLCJkaXNwbGF5IjpbXSwiX3NkIjpbIi1WUFBOUEphMkdTbWo5WHlBZXRzb1laWkYtYkRyRHFEb2lkUWl4WTQwcEkiXX0.7DItRsC1Pg6dcV5GFbyiFQpB3k3FnKF0bUlBmuaEgZEsWNRehBTR2Scfj3mHkFs11JIUOHpxewJEvBfr-5C_Aw~WyJOODdkTTNJZnJhdF9PeW45UVFSZC1BIiwiYmlydGhkYXRlIiwiMTk0MC0wMS0wMSJd~",
}
}
