A web component that fetches a digital credentials request, calls the digital credentials API, and posts the response to your backend.
This project is being actively maintained by the development team at walt.id.
Regular updates, bug fixes, and new features are being added.
Reusable Digital Credentials API web component plus a minimal demo backend. Includes vanilla, React, and Vue demos that hit real verifier endpoints through the in-repo backend middleware.
NOTE: This project is still in development and is not yet ready for production use. It is still an experimental standard.
Use our deployed version here: https://digital-credentials.walt.id
Learn more about the Digital Credentials API:
This project has been tested specifically with the following wallets:
@waltid/digital-credentials— Web Component.<digital-credentials-button>fetches a DC request, callsnavigator.credentials.get, and posts the response to your backend.@waltid/dc-client— Core logic (no UI) to load a request, invoke the DC API, and post verification.@waltid/dc-backend-demo— Lightweight dev-server middleware that creates verifier sessions frompackages/dc-backend-demo/config/*-conf.jsonand exposes/api/dc/request/:idand/api/dc/response.
apps/web-demo— vanilla TS with request selector, toggles, event log, and modal showing verified data.apps/react-demo— minimal React starter that only embeds<digital-credentials-button>to show integration.apps/vue-demo— minimal Vue starter that only embeds<digital-credentials-button>to show integration.
All demos talk to /api/dc/request and /api/dc/response served by the demo backend (Vite plugin).
- Request endpoint:
/api/dc/request/:requestId(also accepts?request-id=). Usespackages/dc-backend-demo/config/<id>-conf.jsonto create a verifier session and return the DC API payload. - Verification endpoint:
/api/dc/responseforwards the credential response to the verifier session and returns verifier info. - Default verifier base:
https://verifier2.portal.test.waltid.cloud(override withVERIFIER_BASEordcDemoBackend({ verifierBase })). - Request IDs available out of the box:
unsigned-mdl,signed-mdl,encrypted-mdl,unsigned-encrypted-mdl,signed-encrypted-mdl,unsigned-photoid,signed-photoid.
The Digital Credentials flow involves three main components working together: the web component (client), the middleware backend, and the verifier service. Here's how they interact:
When a user clicks the <digital-credentials-button>, the web component begins the credential request flow.
Client Middleware Verifier Service
| | |
|-- GET /api/dc/request/:id->| |
| |-- Read config file |
| | (config/{id}-conf.json) |
| | |
| |-- POST /verification-session |
| | /create |
| | (with config JSON) ------->|
| | |
| |<-- sessionId ----------------|
| | |
| |-- GET /verification-session/ |
| | {sessionId}/request ------>|
| | |
| |<-- DC API request payload ---|
| | |
|<-- DC API request payload--| |
Details:
- The client sends a
GETrequest to/api/dc/request/:requestId - The middleware reads the corresponding config file from
packages/dc-backend-demo/config/{requestId}-conf.json - The middleware creates a verification session by posting the config to
{VERIFIER_BASE}/verification-session/create - The verifier returns a
sessionIdwhich the middleware stores - The middleware fetches the DC API request payload from
{VERIFIER_BASE}/verification-session/{sessionId}/request - The middleware returns this payload to the client
Client Browser/Wallet
| |
|-- navigator.credentials.get|
| (with request payload) ->|
| |
| |-- User selects credential |
| | and approves request |
| | |
|<-- Credential response ----|
Details:
- The client calls
navigator.credentials.get()with the request payload - If the browser supports the DC API, it opens the wallet interface
- The user selects and approves the credential request
- The browser/wallet returns the credential response
Client Middleware Verifier Service
| | |
|-- POST /api/dc/response | |
| (with credential) ------>| |
| |-- Lookup sessionId |
| | (from stored sessions) |
| | |
| |-- POST /verification-session |
| | /{sessionId}/response |
| | (with credential) ------->|
| | |
| |-- Poll GET /verification- |
| | session/{sessionId}/info ->|
| | (until status != |
| | "processing") |
| | |
| |<-- Verification result ------|
| | |
|<-- Verification result ----| |
Details:
- The client sends a
POSTrequest to/api/dc/responsewith the credential response - The middleware retrieves the stored
sessionIdfor the request - The middleware forwards the credential to
{VERIFIER_BASE}/verification-session/{sessionId}/response - The middleware polls
{VERIFIER_BASE}/verification-session/{sessionId}/infountil verification completes (status is no longer "processing" or "received") - The middleware returns the verification result to the client
- The web component emits events (
credential-verification-successorcredential-verification-error) with the result
- Request Phase: Client requests → Middleware creates verifier session → Verifier returns DC API payload → Client receives payload
- DC API Phase: Client invokes
navigator.credentials.get()→ User approves in wallet → Browser returns credential - Verification Phase: Client posts credential → Middleware forwards to verifier → Verifier processes → Middleware polls for result → Client receives verification
At each stage, errors are caught and emitted as events:
credential-request-loaded- Request payload successfully fetchedcredential-dcapi-error- DC API call failed (e.g., user cancelled, unsupported browser)credential-verification-error- Verification failed (e.g., invalid credential, verifier error)credential-error- Generic error at any stage
npm install
npm run build # builds demo backend, core client, and web component
npm run dev:web # vanilla demo
npm run dev:react # React demo
npm run dev:vue # Vue demoOpen the served URL (Vite defaults to 5173). The web demo includes request selection, toggles, and logging; the React/Vue demos are minimal starters that simply render the web component pointed at the demo backend.
<script type="module">
import '@waltid/digital-credentials';
</script>
<digital-credentials-button
request-id="unsigned-mdl"
request-endpoint="/api/dc/request"
response-endpoint="/api/dc/response"
label="Request credentials"
></digital-credentials-button>Optionally skip fetching by passing a payload directly via request-payload (JSON string) or the requestPayload property.
Target parts: ::part(button) and ::part(status). The demos include an icon/gradient example in their CSS.
el.addEventListener('credential-request-loaded', (e) => console.log(e.detail.payload));
el.addEventListener('credential-verification-success', (e) => console.log(e.detail.response));
el.addEventListener('credential-error', (e) => console.error(e.detail));// vite.config.ts
import { defineConfig } from 'vite';
import { dcDemoBackend } from '@waltid/dc-backend-demo';
export default defineConfig({
plugins: [dcDemoBackend({ verifierBase: 'https://verifier.example.com' })]
});- Point
<digital-credentials-button>at your backend withrequest-endpointandresponse-endpoint; keeprequest-idto pick the verifier config you want. - Backend flow: (1)
POST ${VERIFIER_BASE}/verification-session/createwith the config JSON you want (seepackages/dc-backend-demo/config/*-conf.jsonas templates) and storesessionId; (2)GET ${VERIFIER_BASE}/verification-session/{sessionId}/requestand return that JSON to the web component; (3) when the component POSTs the DC API result to yourresponse-endpoint, forward it toPOST ${VERIFIER_BASE}/verification-session/{sessionId}/responseand return the verifier reply (poll/infountil it’s ready). - Keep
VERIFIER_BASEas an environment variable so you can swap verifier deployments without code changes.
npm run build— builds demo backend, core client, and web component.npm run build:backend— demo backend only.npm run build:client— core client only.npm run build:wc— web component only.npm run dev:web|react|vue— run the respective demo with the demo backend middleware.
- Connect and get the latest updates: Discord | Newsletter | YouTube | LinkedIn
- Get help, request features and report bugs: GitHub Issues
- Find more indepth documentation on our docs site
Licensed under the Apache License, Version 2.0
