---
title: "Presenting Credentials via OID4VP"
description: "Learn how to present verifiable credentials from the Wallet SDK over OID4VP 1.0 with DCQL."
stack: "Community Stack (open source) — 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/community-stack/mobile-wallet/present-credentials
generated: 2026-10-01
---
# Presenting Credentials via OID4VP

This guide shows you how to present a verifiable credential from the walt.id Wallet SDK using [OID4VP 1.0](https://docs.walt.id/concepts/data-exchange-protocols/openid4vp.md) with [DCQL](https://docs.walt.id/concepts/data-exchange-protocols/dcql.md) for matching. You hand the wallet a presentation request — typically an `openid4vp://` URL from [Portal2](https://portal2.demo.walt.id) — and the wallet finds matching credentials, builds a presentation, and submits it.

[**OID4VP**](https://docs.walt.id/concepts/data-exchange-protocols/openid4vp.md): The protocol used to deliver a presentation from the wallet to the verifier.

[**DCQL**](https://docs.walt.id/concepts/data-exchange-protocols/dcql.md): The query language the verifier uses to describe which credentials and claims it needs.

**Note:**

Presentation is preview → consent → submit or reject. Isolated steps keep the SDK from sending anything until the holder approves. For in-person mdoc sharing, use [Proximity Sharing](https://docs.walt.id/community-stack/mobile-wallet/proximity-sharing.md) instead of an OID4VP URL.

## Prerequisites

Before you begin, ensure you have:

- **A wallet that already holds a matching credential** — Receive one first with [Receiving Credentials via OID4VCI](https://docs.walt.id/community-stack/mobile-wallet/receive-credentials.md) or a [sample app](https://docs.walt.id/community-stack/mobile-wallet/try-the-demo.md).
- **A presentation request** — Create one in [portal2.demo.walt.id](https://portal2.demo.walt.id), or follow a Verifier2 guide such as [SD-JWT VC via OID4VP](https://docs.walt.id/community-stack/verifier2/credential-verification/sd-jwt-vc-oid4vp.md).

**Note:**

Always test present through [portal2.demo.walt.id](https://portal2.demo.walt.id).

---

## How Presentation Works

```mermaid
sequenceDiagram
    participant App
    participant SDK
    participant Verifier
    App->>SDK: previewPresentation request URL
    SDK->>Verifier: Resolve request
    SDK-->>App: Verifier metadata and credential options
    App->>App: Holder reviews claims and consents
    App->>SDK: submitPresentation or rejectPresentation
    SDK->>Verifier: VP token or denial
```

1. Preview the request to resolve verifier metadata, response encryption, DCQL matches, and transaction data.
2. Show the verifier name, the claims that will be shared, and any response-encryption state.
3. Submit the holder's selection, or reject the request. Omitting an error on reject sends `access_denied` for a valid request.

## Preview and Submit

The same session APIs work for [SD-JWT VC](https://docs.walt.id/concepts/digital-credentials/sd-jwt-vc.md), [W3C VC](https://docs.walt.id/concepts/digital-credentials/verifiable-credentials-w3c.md), and [ISO 18013-5 mDL](https://docs.walt.id/concepts/digital-credentials/mdoc-mdl-iso.md). Preview currently covers signed requests, encrypted responses, and OpenID4VP transaction data.

**Option: Kotlin**

```kotlin
when (val result = wallet.previewPresentation(requestUrl)) {
    is MobileWalletPresentationPreviewResult.Invalid -> {
        showRequestError(result.message)
        wallet.rejectPresentation(result.previewHandle)
    }
    is MobileWalletPresentationPreviewResult.Ready -> {
        val preview = result.preview
        preview.request.verifierMetadata?.display?.name?.let(::showVerifierName)
        when (val encryption = preview.request.responseEncryption) {
            MobileWalletResponseEncryption.NotRequired -> showPlainResponseNotice()
            is MobileWalletResponseEncryption.Required -> showEncryptedResponseNotice(
                algorithm = encryption.keyManagementAlgorithm,
                contentEncryption = encryption.contentEncryptionAlgorithm,
                verifierKeyId = encryption.verifierKeyId,
                verifierKeyThumbprint = encryption.verifierKeyThumbprint,
            )
        }
        val outcome = wallet.submitPresentation(
            previewHandle = preview.previewHandle,
            selectedCredentialOptions = preview.credentialOptions.map {
                MobileWalletPresentationCredentialSelection(
                    queryId = it.queryId,
                    credentialId = it.credentialId,
                )
            },
            did = identity.did,
        )
    }
}
```

**Option: Swift**

```swift
switch try await wallet.previewPresentation(request: authorizationRequestURL) {
case .ready(let preview):
    if let verifierName = preview.request.verifierMetadata?.display?.name {
        showVerifierName(verifierName)
    }
    let result = try await wallet.submitPresentation(
        previewHandle: preview.previewHandle,
        selectedCredentialOptions: preview.credentialOptions.map(\.selection),
        did: identity.did
    )
case .invalid(let error):
    showRequestError(error.message)
    _ = try await wallet.rejectPresentation(previewHandle: error.previewHandle)
}
```

**Note:**

Response-encryption metadata describes protection of the authorization response. It does not establish verifier trust and does not expose verifier key material.

🎉 You've presented a credential to the verifier.

---

## Selective Disclosure and Transaction Data

The verifier asks for claims through the `claims` array of its DCQL query. Preview returns required and selectable claims so your UI can show exactly what will be shared.

When the request includes OpenID4VP `transaction_data`, pass the profile types your app understands in wallet configuration. Unknown types are rejected before submit. Profile fields stay available for UI.

## Next Steps

- **Share an mdoc in person** — [Proximity Sharing](https://docs.walt.id/community-stack/mobile-wallet/proximity-sharing.md).
- **Present through the OS picker** — [Digital Credentials API](https://docs.walt.id/community-stack/mobile-wallet/digital-credentials-api.md).
- **Configure signing policy and reader trust** — [Security](https://docs.walt.id/community-stack/mobile-wallet/security.md).
