---
title: "How to Accept SD-JWT VC Credentials via OID4VCI in a Wallet with walt.id"
description: "Accept SD-JWT VC credentials (IETF) in the walt.id wallet via OID4VCI—learn the credential offer format, API call, and how selective disclosures appear in the response."
stack: "Community Stack (open source) — version 0.21.0"
stack_version: "0.21.0"
stack_comparison: https://docs.walt.id/community-vs-enterprise.md
canonical_url: https://docs.walt.id/community-stack/wallet/credential-exchange/guides/accept-sd-jwt-vc-oid4vci
generated: 2026-07-08
---
# How to Accept SD-JWT VC Credentials via OID4VCI in a Wallet with walt.id

**TL;DR**

**What you:**

- Recognise the SD-JWT VC credential offer format
- Accept SD-JWT VC credential offers via the Wallet API
- Understand how selective disclosures appear in the API response

**Relevant concepts:**

- [OpenID4VCI](https://docs.walt.id/concepts/data-exchange-protocols/openid4vci.md) – Protocol for verifiable credential issuance
- [SD-JWT VC (IETF)](https://docs.walt.id/concepts/digital-credentials/sd-jwt-vc.md) – IETF standard for selectively disclosable credentials
- [Selective Disclosure](https://docs.walt.id/concepts/selective-disclosure.md) – Sharing only chosen attributes from a credential

The API call to accept an SD-JWT VC credential is identical to accepting a W3C VC — the same
`/wallet-api/wallet/{walletId}/exchange/useOfferRequest` endpoint is used. The differences lie in the
**credential offer format** and the **structure of the response**.

## Credential Offer URL

As with all OID4VCI issuance, the issuer communicates the credential offer via a URL beginning
with `openid-credential-offer://`.

**Example Offer URL**

```
openid-credential-offer://issuer.portal.walt.id/?credential_offer=<credential_offer>
```

**Example Credential Offer Object**

For SD-JWT VCs, the offer uses a `vct` field (Verifiable Credential Type) instead of the `types` array used by
W3C credentials. This URI uniquely identifies the credential type defined by the issuer.

```json
{
  "credential_issuer": "https://issuer.demo.walt.id",
  "credential_configuration_ids": [
    "identity_credential"
  ],
  "grants": {
    "urn:ietf:params:oauth:grant-type:pre-authorized_code": {
      "pre-authorized_code": "<pre-authorized_code>",
      "user_pin_required": false
    }
  }
}
```

## Accepting Credential Offers

**Option: CURL**

**Endpoint:** `/wallet-api/wallet/{walletId}/exchange/useOfferRequest` | [API Reference](https://wallet.demo.walt.id/swagger/index.html#/Credential%20exchange/post_wallet_api_wallet__wallet__exchange_useOfferRequest)

**Example Request**

```bash
curl -X 'POST' \
  'http://0.0.0.0:7001/wallet-api/wallet/{walletId}/exchange/useOfferRequest?did={did}' \
  -H 'accept: application/json' \
  -H 'Content-Type: text/plain' \
  -H 'authorization: Bearer {token}' \
  -d 'openid-credential-offer://issuer.portal.walt.id/?credential_offer=<credential_offer>'
```

**Path Parameters**

- `walletId`: _String_ - The ID of the wallet to receive the credential into. See [Accounts & Wallets](https://docs.walt.id/community-stack/wallet/accounts-wallets.md#retrieve-wallet-id) for how to retrieve it.

**Query Parameters**

- `did` (optional): _String_ - The DID of the wallet holder to use when accepting the credential. If omitted, the wallet's default DID is used.

**Header Parameters**

- `authorization`: _String_ - Bearer token obtained from the [login endpoint](https://docs.walt.id/community-stack/wallet/authentication/email-password-auth.md#login). Format: `Bearer {token}`.

**Body**

The credential offer URL received from the issuer, provided as plain text.

```
openid-credential-offer://issuer.portal.walt.id/?credential_offer=<credential_offer>
```

**Note:**

  When using the terminal, the credential offer URL returned from the issuer may have a `%` at the end. Make sure to remove this before passing it to the wallet.

---

**Example Response**

On success, the API returns a list of the credentials received and stored in the wallet.

```json
[
  {
    "wallet": "6006b6f4-e651-46db-b6ae-e7bd6e9c40f2",
    "id": "urn:uuid:48841c75-36cb-416b-af2e-6d4e606c8ca6",
    "document": "eyJraWQiOiJkaWQ6a2V5Ono2TWtqb1JocTFqU05KZExpcnVTWHJGRnhhZ3FyenRaYVhIcUhHVVRLSmJjTnl3cCN6Nk1ram9SaHExalNOSmRMaXJ1U1hyRkZ4YWdxcnp0WmFYSHFIR1VUS0piY055d3AiLCJ0eXAiOiJ2YytzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJnaXZlbl9uYW1lIjoiSm9obiIsImZhbWlseV9uYW1lIjoiRG9lIiwiZW1haWwiOiJqb2huZG9lQGV4YW1wbGUuY29tIiwicGhvbmVfbnVtYmVyIjoiKzEtMjAyLTU1NS0wMTAxIiwiYWRkcmVzcyI6eyJzdHJlZXRfYWRkcmVzcyI6IjEyMyBNYWluIFN0IiwibG9jYWxpdHkiOiJBbnl0b3duIiwicmVnaW9uIjoiQW55c3RhdGUiLCJjb3VudHJ5IjoiVVMifSwiaXNfb3Zlcl8xOCI6dHJ1ZSwiaXNfb3Zlcl8yMSI6dHJ1ZSwiaXNfb3Zlcl82NSI6dHJ1ZSwiaWQiOiJ1cm46dXVpZDo0ODg0MWM3NS0zNmNiLTQxNmItYWYyZS02ZDRlNjA2YzhjYTYiLCJpYXQiOjE3NzYzNTIzNjEsIm5iZiI6MTc3NjM1MjM2MSwiZXhwIjoxODA3ODg4MzYxLCJfc2RfYWxnIjoic2hhLTI1NiIsImlzcyI6ImRpZDprZXk6ejZNa2pvUmhxMWpTTkpkTGlydVNYckZGeGFncXJ6dFphWEhxSEdVVEtKYmNOeXdwIiwiY25mIjp7Imp3ayI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoialo0WlFHampnLXpYRmZGNFpmbldfZDhXYkljZ0VYSW9uNGhJbXhhYzRiZyIsIngiOiJuMUNoQTNJSU1SdkVNSm51V055djU0bTVrZURhay1leHN0N3F6eXdPTmZFIiwieSI6Il9qWVN6U19Db3RQX2dMMGxiVUNyZWVOTmU4MXIweHEzMlllSjJ0NG1xblkifX0sInZjdCI6Imh0dHBzOi8vaXNzdWVyLmRlbW8ud2FsdC5pZC9kcmFmdDEzL2lkZW50aXR5X2NyZWRlbnRpYWwiLCJfc2QiOlsid2NXMkJXU2g5MXhneHh1RjhFckJJMkkxOVpoUEFST2pBTEtoZGRrX0JXUSJdfQ.u198RgZC1pv3VbZy7DbMHh6g432qnT4AIHhploWyyITtW5PCbUp_6ewJBvNjwf1tfNu8cDhcdP8E4UyG0djZAQ",
    "disclosures": "WyJVd3hscTJaX2ZCdlpZNGF2Y2JDTWpRIiwiYmlydGhkYXRlIiwiMTk0MC0wMS0wMSJd",
    "addedOn": "2026-04-16T15:12:41.345828048Z",
    "pending": false,
    "format": "vc+sd-jwt",
    "parsedDocument": {
      "given_name": "John",
      "family_name": "Doe",
      "email": "johndoe@example.com",
      "phone_number": "+1-202-555-0101",
      "address": {
        "street_address": "123 Main St",
        "locality": "Anytown",
        "region": "Anystate",
        "country": "US"
      },
      "is_over_18": true,
      "is_over_21": true,
      "is_over_65": true,
      "id": "urn:uuid:48841c75-36cb-416b-af2e-6d4e606c8ca6",
      "iat": 1776352361,
      "nbf": 1776352361,
      "exp": 1807888361,
      "_sd_alg": "sha-256",
      "iss": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
      "cnf": {
        "jwk": {
          "kty": "EC",
          "crv": "P-256",
          "kid": "jZ4ZQGjjg-zXFfF4ZfnW_d8WbIcgEXIon4hImxac4bg",
          "x": "n1ChA3IIMRvEMJnuWNyv54m5keDak-exst7qzywONfE",
          "y": "_jYSzS_CotP_gL0lbUCreeNNe81r0xq32YeJ2t4mqnY"
        }
      },
      "vct": "https://issuer.demo.walt.id/draft13/identity_credential",
      "_sd": ["wcW2BWSh91xgxxuF8ErBI2I19ZhPAROjALKhddk_BWQ"]
    }
  }
]
```

**Response Fields**

- `wallet`: _String_ - The ID of the wallet the credential was stored in.
- `id`: _String_ - The unique identifier of the stored credential.
- `document`: _String_ - The raw signed SD-JWT token.
- `disclosures`: _String_ - Base64url-encoded disclosure(s) included with the credential. Each disclosure
  encodes a salt, claim name, and claim value — representing a selectively disclosable attribute the
  holder can choose to reveal when presenting. Decoding the value from the example above gives:
  ```json
  ["Uwxlq2Z_fBvZY4avcbCMjQ", "birthdate", "1940-01-01"]
  ```
- `addedOn`: _String_ - ISO 8601 timestamp of when the credential was stored.
- `pending`: _Boolean_ - Whether the credential is pending acceptance.
- `format`: _String_ - The credential format. `vc+sd-jwt` identifies this as an IETF SD-JWT VC.
- `parsedDocument`: _Object_ - The decoded credential claims as a flat JSON object. Key fields include:
  - `vct`: _String_ - The Verifiable Credential Type URI identifying the credential type.
  - `iss`: _String_ - The DID of the issuer.
  - `cnf.jwk`: _Object_ - The holder's public key, binding the credential to the wallet.
  - `_sd_alg`: _String_ - The hash algorithm used for selective disclosure (typically `sha-256`).
  - `_sd`: _Array_ - Hashes of claims that are selectively disclosable but withheld in this issuance.
  - `iat`, `nbf`, `exp`: _Number_ - Issued at, not before, and expiration timestamps (Unix).
