---
title: "Accept W3C Verifiable Credentials via OID4VCI"
description: "Learn how to receive and store W3C Verifiable Credentials via OID4VCI using the walt.id Enterprise wallet API."
stack: "Enterprise Stack (commercial) — version 1.1.1"
stack_version: "1.1.1"
stack_comparison: https://docs.walt.id/community-vs-enterprise.md
canonical_url: https://docs.walt.id/enterprise-stack/services/wallet-service/credential-receiving/vc-oid4vci
generated: 2026-10-01
---
# Accept W3C Verifiable Credentials (JWT) via OID4VCI

In this guide, we take a look at how you can use the walt.id Enterprise wallet service API
to accept a W3C Verifiable Credential from an issuer via OID4VCI.

**Note:**

Ensure you have [set up a wallet (service)](https://docs.walt.id/enterprise-stack/services/wallet-service/setup.md) and linked the necessary enterprise services (e.g.,
Credential Store) before proceeding
with this guide.

<br/>

**Note:**

This guide refers specifically to W3C Verifiable Credential standard without selective disclosure. It is possible to wrap a W3C Verifiable Credential within an SD-JWT in order to support selective disclosure. To understand more, check out the [Issue W3C Credentials (JWT / SD-JWT) via OID4VC](https://docs.walt.id/enterprise-stack/services/issuer-service/credential-issuance/vc-oid4vc.md) 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>
```

Within the URL, a query parameter `credential_offer` or `credential_offer_uri` provides either the actual offer as a
JSON object or a URL that points to the JSON object.

**Example of a Credential Offer Object for JWT VCs**

```json
{
  "credential_issuer": "https://issuer.demo.walt.id",
  "credentials": [
    {
      "format": "jwt_vc_json",
      "types": [
        "VerifiableCredential",
        "BankId"
      ],
      "credential_definition": {
        "@context": [
          "https://www.w3.org/2018/credentials/v1"
        ],
        "types": [
          "VerifiableCredential",
          "BankId"
        ]
      }
    }
  ],
  "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 Credential Offers

In the next step, we will provide the credential offer URL to a wallet service endpoint. This will initialize the
exchange between wallet and issuer. The response of the call will contain the received credential, which will also
be stored in the linked credential store. In case there is no linked the credential store, the credential won't be
stored and must be saved otherwise if later retrieval is wanted.

**Note:**

If there is no credential stored linked with the wallet the received
credential won't be persisted.

<br/>

**Option: CURL**

Endpoint: `/v1/{target}/wallet-service-api/credentials/receive` | [API Reference](https://enterprise.sandbox.walt.id/swagger/index.html#/Service%20%7C%20Wallet%20Service/post_v1__target__wallet_service_api_credentials_receive)

**Example Request**

```bash
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 named `test`, your default Base URL will
  be `test.enterprise-sandbox.walt.dev` when 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**

```json
{
  "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"
}
```

**Body Parameters**

- `offerUrl` _String_ - An OID4VCI offer URL.
- `keyReference` (optional) _String_ - The resource ID (target) of the key to which the received credential should be
  bound. Key can be stored in a linked KMS store, provided as a static key as described
  in [the setup section](https://docs.walt.id/enterprise-stack/services/wallet-service/setup.md), or
  just a raw Key object. See example by expanding.
- `didReference` (optional) _String_ - The DID reference of a DID stored in a linked DID Store. Returns an error if the referenced DID does not exist.
- `key` (optional) _Object_ - A key object or reference key object, when using an external KMS, to which the credential
  should be bound to.
  <br/>
  <br/>
  <details><summary>Click to expand and see full key example</summary>

  <br/>

  **Key Object**

   ```json
    {
    "type": "jwk",
    "jwk": {
      "kty": "OKP",
      "d": "ywmoRVTD9fexMtGW0lKE3o9_0ulfzGXr9xHGL0lPhhA",
      "crv": "Ed25519",
      "kid": "IQO7DILxtagpTLXkuHkRkJURb2GqcUIwXYZAcGwW1AU",
      "x": "JOsiIE7ME9UZ8y2H-P5RSuYAUiIfs1ywtdBjMGN7I5s"
    }
  }
   ```
  This key object can also be of the types `tse`, `aws`, or `oci-rest-api` when using external KMS providers. In this
  case, instead of providing the raw key, an object containing reference information that allows the walt.id Enterprise 
  Stack to access keys stored externally is provided. Learn more about different keys [here](https://docs.walt.id/enterprise-stack/services/key-management-service/overview.md).

   </details>
- `did` (optional) _String_ - DID as a string, e.g. `did:key:z6MktjQeU9dZp8VfK8M9N8Y2u5wV6JzZ2v6s6Q1P7pRkFJ8H`
- `metadata` (optional) _Object_ - Arbitrary JSON object that will be stored together with the credential if there is a
credential store linked with the wallet.
- `runPolicies` (optional) _Boolean_ - If set to `true`, the wallet service will run any [holder policies](https://docs.walt.id/enterprise-stack/services/holder-policy-store-service/overview.md) that are
  attached to the wallet service before storing the credential. If set to `false`, no holder policies will be run.

---

**Response Codes**

- `201` - Credential received successfully.

**Body**

```json
{
    "offeredCredential": {
      "format": "jwt_vc_json",
      "credential_definition": {
        "type": [
          "VerifiableCredential",
          "OpenBadgeCredential"
        ]
      },
      "cryptographic_binding_methods_supported": [
        "did"
      ],
      "customParameters": {}
    },
    "credentialResponse": {
      "format": "jwt_vc_json",
      "credential": "eyJraWQiOiJkaWQ6a2V5Ono2TWtqb1JocTFqU05KZExpcnVTWHJGRnhhZ3FyenRaYVhIcUhHVVRLSmJjTnl3cCN6Nk1ram9SaHExalNOSmRMaXJ1U1hyRkZ4YWdxcnp0WmFYSHFIR1VUS0piY055d3AiLCJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJkaWQ6a2V5Ono2TWtqb1JocTFqU05KZExpcnVTWHJGRnhhZ3FyenRaYVhIcUhHVVRLSmJjTnl3cCIsInN1YiI6IiIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly9wdXJsLmltc2dsb2JhbC5vcmcvc3BlYy9vYi92M3AwL2NvbnRleHQuanNvbiJdLCJpZCI6InVybjp1dWlkOjIyNGJjYmM0LTc0MzYtNDg1NC04ZWYxLWNjNmUzYjgyMzZiZCIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJPcGVuQmFkZ2VDcmVkZW50aWFsIl0sIm5hbWUiOiJKRkYgeCB2Yy1lZHUgUGx1Z2Zlc3QgMyBJbnRlcm9wZXJhYmlsaXR5IiwiaXNzdWVyIjp7InR5cGUiOlsiUHJvZmlsZSJdLCJuYW1lIjoiSm9icyBmb3IgdGhlIEZ1dHVyZSAoSkZGKSIsInVybCI6Imh0dHBzOi8vd3d3LmpmZi5vcmcvIiwiaW1hZ2UiOiJodHRwczovL3czYy1jY2cuZ2l0aHViLmlvL3ZjLWVkL3BsdWdmZXN0LTEtMjAyMi9pbWFnZXMvSkZGX0xvZ29Mb2NrdXAucG5nIiwiaWQiOiJkaWQ6a2V5Ono2TWtqb1JocTFqU05KZExpcnVTWHJGRnhhZ3FyenRaYVhIcUhHVVRLSmJjTnl3cCJ9LCJjcmVkZW50aWFsU3ViamVjdCI6eyJ0eXBlIjpbIkFjaGlldmVtZW50U3ViamVjdCJdLCJhY2hpZXZlbWVudCI6eyJpZCI6InVybjp1dWlkOmFjMjU0YmQ1LThmYWQtNGJiMS05ZDI5LWVmZDkzODUzNjkyNiIsInR5cGUiOlsiQWNoaWV2ZW1lbnQiXSwibmFtZSI6IkpGRiB4IHZjLWVkdSBQbHVnRmVzdCAzIEludGVyb3BlcmFiaWxpdHkiLCJkZXNjcmlwdGlvbiI6IlRoaXMgd2FsbGV0IHN1cHBvcnRzIHRoZSB1c2Ugb2YgVzNDIFZlcmlmaWFibGUgQ3JlZGVudGlhbHMgYW5kIGhhcyBkZW1vbnN0cmF0ZWQgaW50ZXJvcGVyYWJpbGl0eSBkdXJpbmcgdGhlIHByZXNlbnRhdGlvbiByZXF1ZXN0IHdvcmtmbG93IGR1cmluZyBKRkYgeCBWQy1FRFUgUGx1Z2Zlc3QgMy4iLCJjcml0ZXJpYSI6eyJ0eXBlIjoiQ3JpdGVyaWEiLCJuYXJyYXRpdmUiOiJXYWxsZXQgc29sdXRpb25zIHByb3ZpZGVycyBlYXJuZWQgdGhpcyBiYWRnZSBieSBkZW1vbnN0cmF0aW5nIGludGVyb3BlcmFiaWxpdHkgZHVyaW5nIHRoZSBwcmVzZW50YXRpb24gcmVxdWVzdCB3b3JrZmxvdy4gVGhpcyBpbmNsdWRlcyBzdWNjZXNzZnVsbHkgcmVjZWl2aW5nIGEgcHJlc2VudGF0aW9uIHJlcXVlc3QsIGFsbG93aW5nIHRoZSBob2xkZXIgdG8gc2VsZWN0IGF0IGxlYXN0IHR3byB0eXBlcyBvZiB2ZXJpZmlhYmxlIGNyZWRlbnRpYWxzIHRvIGNyZWF0ZSBhIHZlcmlmaWFibGUgcHJlc2VudGF0aW9uLCByZXR1cm5pbmcgdGhlIHByZXNlbnRhdGlvbiB0byB0aGUgcmVxdWVzdG9yLCBhbmQgcGFzc2luZyB2ZXJpZmljYXRpb24gb2YgdGhlIHByZXNlbnRhdGlvbiBhbmQgdGhlIGluY2x1ZGVkIGNyZWRlbnRpYWxzLiJ9LCJpbWFnZSI6eyJpZCI6Imh0dHBzOi8vdzNjLWNjZy5naXRodWIuaW8vdmMtZWQvcGx1Z2Zlc3QtMy0yMDIzL2ltYWdlcy9KRkYtVkMtRURVLVBMVUdGRVNUMy1iYWRnZS1pbWFnZS5wbmciLCJ0eXBlIjoiSW1hZ2UifX19LCJpc3N1YW5jZURhdGUiOiIyMDI1LTA0LTAzVDA3OjM0OjEzLjUyMjQzMjc1M1oiLCJleHBpcmF0aW9uRGF0ZSI6IjIwMjYtMDQtMDNUMDc6MzQ6MTMuNTIyNTM1MjUzWiJ9LCJqdGkiOiJ1cm46dXVpZDoyMjRiY2JjNC03NDM2LTQ4NTQtOGVmMS1jYzZlM2I4MjM2YmQiLCJleHAiOjE3NzUyMDE2NTMsImlhdCI6MTc0MzY2NTY1MywibmJmIjoxNzQzNjY1NjUzfQ.eu7Owii99m9DGT_L9PPpdOxcjxpBN1CMsPoTvVtMD0WTsatn5c8MCIrr3NFM74CTbVrhe-NAOFseyC9QrFGdDw",
      "customParameters": {}
    }
}
```
