Issue Mortgage Documents to a Personal Wallet
The Story
Imagine Thomas, a software developer who is buying his first apartment in Utrecht for EUR 385,000. To apply for a mortgage, he needs to provide six documents from six different sources: an identity document, a pension overview, a purchase contract, a savings statement, a loan overview, and a student debt statement.
Thomas already has four of these credentials in his personal wallet — his identity document, pension overview, purchase contract, and student debt statement — collected over time from various government and institutional portals. But two are still missing: his savings statement from ING and his loan overview from BKR.
In the old world, Thomas would download PDFs, scan paper statements, and upload files to the bank's portal. But ING and BKR have integrated verifiable credential issuance powered by the Credenco Business Wallet. Thomas visits each portal, a QR code appears, he scans it with his wallet app, and the credential slides in — cryptographically signed, tamper-proof, and instantly verifiable.
The best part? Every institution uses the exact same integration pattern — a single API call. Whether you're a bank, a credit bureau, or any other institution, the process is identical.
This guide shows you how to build that experience.
How It Works
When issuing a mortgage-related credential to a personal wallet, the flow involves three parties: the issuer's portal (where Thomas interacts), the issuer's backend (which orchestrates the process), and the Credenco Business Wallet (which creates and signs the credential).
The credential holder never needs to install special software beyond a wallet app — the credential lands directly in their wallet via a simple QR code scan.
Key Concepts
| Concept | Description |
|---|---|
| Personal Wallet App | A mobile app on the user's phone that stores verifiable credentials (e.g., a wallet compliant with the EUDI Wallet standard) |
| QR Code | The bridge between the web application and the user's mobile wallet — encodes the credential offer |
| OpenID4VCI | The open standard protocol used for credential issuance between the wallet app and the Credenco Business Wallet |
| Correlation ID | A business key you provide to track the issuance process and check its status |
Sequence Diagram
The diagram below shows the complete interaction between all parties — from the moment Thomas requests a credential to the moment it appears in his wallet. This flow is identical for every credential type.
Step-by-Step Integration
Prerequisites
Before you begin, make sure you have:
- A Credenco Business Wallet account (sign up here)
- An Issuer Template configured — Create Issuer Template
- A Credential Template configured — Create Credential Template
- API access enabled — Set up API authentication
Step 1: Start the Credential Issuance
When a user requests a credential from your portal, your backend calls the Start issue Credential API.
Example: Issuing a savings statement credential
Request:
curl -X POST https://your-wallet.credenco.com/api/v2/credential/issue \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"correlation_id": "savings-thomas-2026",
"template_id": "savings_statement",
"claims": {
"bank_name": "ING",
"account_holder": "Thomas van den Berg",
"balance": "47.250",
"balance_date": "2026-03-15"
},
"qr_code": {
"size": 400
}
}'
Tip: The qr_code object is what tells Credenco to generate a QR code for a personal wallet. Without it, the response will contain a deeplink URI instead, suitable for business wallets.
Response:
{
"correlation_id": "savings-thomas-2026",
"request_uri": "openid-credential-offer://?credential_offer_uri=https://your-wallet.credenco.com/openid4vc/credentialOffer?id=a3b7c9d1-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"status_uri": "https://your-wallet.credenco.com/api/v2/issue/savings-thomas-2026",
"qr_uri": "data:image/png;base64,iVBORw0KGgo..."
}
| Field | Description |
|---|---|
correlation_id | Your business key to track this issuance |
request_uri | The OpenID4VCI credential offer URI (encoded in the QR code) |
status_uri | Endpoint to poll for status updates |
qr_uri | Base64-encoded PNG image of the QR code — ready to display |
Step 2: Display the QR Code
The qr_uri in the response is a Data URI containing the QR code as a PNG image. Display it directly in your frontend:
<div style="text-align: center; padding: 2rem;">
<h2>Scan this QR code with your wallet app</h2>
<img src="data:image/png;base64,iVBORw0KGgo..." alt="Savings Statement QR Code" />
<p>Open your wallet app and scan the code to receive your savings statement credential.</p>
</div>
Note: The QR code is a one-time use code. Once scanned and the credential is issued, it cannot be reused. Generate a new one for each issuance.
Step 3: The User Scans the QR Code
From Thomas's perspective:
- Thomas opens his personal wallet app on his phone
- He taps "Scan QR code" (or similar)
- The wallet app reads the QR code and contacts the Credenco Business Wallet
- The wallet and Credenco exchange the credential using the OpenID4VCI protocol
- Thomas sees his new credential in his wallet and accepts it
The issuer's portal doesn't need to do anything during this step — the wallet app and Credenco handle everything automatically.
Step 4: Check the Issuance Status
After the QR code is displayed, your backend can poll the Get issue status API to track progress:
curl https://your-wallet.credenco.com/api/v2/credential/issue/savings-thomas-2026 \
-H "x-api-key: YOUR_API_KEY"
Response (after credential is accepted):
{
"status": "issue_completed",
"correlation_id": "savings-thomas-2026",
"last_updated": 1751155200000,
"revocation_uuid": "7f3a2b1c-9d8e-4f5a-6b7c-8d9e0f1a2b3c"
}
| Status | Meaning |
|---|---|
issue_request_created | The credential offer has been created, waiting for the wallet to pick it up |
credential_offer_retrieved | The wallet app has retrieved the offer |
issue_completed | The credential has been successfully issued and accepted |
error | Something went wrong during the issuance process |
Tip: Save the revocation_uuid from the completed response. You'll need it if you ever want to revoke the credential in the future.
Optional: Use Callbacks Instead of Polling
Instead of polling the status endpoint, you can provide a callback URL in the issue request. Credenco will notify your backend automatically when the status changes:
{
"correlation_id": "savings-thomas-2026",
"template_id": "pension_overview",
"claims": { ... },
"qr_code": { "size": 400 },
"callback": {
"url": "https://your-backend.com/webhooks/credential-status",
"status": ["issue_completed", "error"]
}
}
Your callback endpoint will receive a POST request with the status update whenever the issuance completes or fails.
Credential Examples
Each institution issues a different credential type. Below are example claims payloads for each of the six mortgage documents.
Identity Document
Issued by the municipality (e.g., Municipality of Utrecht).
{
"template_id": "identity_document",
"claims": {
"full_name": "Thomas van den Berg",
"date_of_birth": "1994-02-18",
"bsn": "123456789",
"document_number": "IDNLD12345",
"valid_until": "2031-02-18"
}
}
Pension Overview
Issued by the pension overview portal (mijnpensioenoverzicht.nl).
{
"template_id": "pension_overview",
"claims": {
"full_name": "Thomas van den Berg",
"pension_provider": "ABP Pensioenfonds",
"annual_accrual": "2.450",
"total_accrued": "42.150",
"retirement_date": "2059-06-15"
}
}
Purchase Contract
Issued by the notary handling the property sale.
{
"template_id": "purchase_contract",
"claims": {
"property_address": "Oudegracht 42, 3511 AR Utrecht",
"purchase_price": "385000",
"buyer_name": "Thomas van den Berg",
"seller_name": "Maria Jansen",
"signing_date": "2026-03-01"
}
}
Savings Statement
Issued by the applicant's bank (e.g., ING).
{
"template_id": "savings_statement",
"claims": {
"bank_name": "ING",
"account_holder": "Thomas van den Berg",
"balance": "47.250",
"balance_date": "2026-03-15"
}
}
Loan Overview
Issued by BKR (Bureau Krediet Registratie).
{
"template_id": "loan_overview",
"claims": {
"full_name": "Thomas van den Berg",
"total_debt": "2.800",
"monthly_obligations": "150",
"number_of_loans": "1",
"registration_date": "2026-03-10"
}
}
Student Debt Statement
Issued by DUO (Dienst Uitvoering Onderwijs).
{
"template_id": "student_debt_statement",
"claims": {
"full_name": "Thomas van den Berg",
"original_debt": "28.000",
"remaining_debt": "18.500",
"monthly_payment": "185",
"expected_end_date": "2034-09-01"
}
}
Complete Flow at a Glance
Calls the Issue API with the credential details and requests a QR code
Display the returned QR code in the issuer's portal
Thomas scans the QR code with his personal wallet app
The wallet and Credenco exchange the credential via OpenID4VCI
API Reference
| API | Method | Endpoint | Description |
|---|---|---|---|
| Start issue Credential | POST | /api/v2/credential/issue | Start the credential issuance and get a QR code |
| Get issue status | GET | /api/v2/credential/issue/{correlationId} | Check the status of an issuance process |
| Revoke Credential | POST | /api/v2/credential/revoke | Revoke a previously issued credential |
What's Next?
Now that you understand how to issue mortgage credentials to a personal wallet, you might want to explore:
- Verify Mortgage Documents — See how the bank verifies all six credentials at once
- Create Credential Templates — Design the credential types your organization issues
- API Authentication — Set up OAuth2 or API key authentication
- Verify Credentials — Request and verify credentials from holders