Skip to main content

Overview

Digital Credentials integration lets you verify identity documents (passports, ID cards, driver’s licenses) stored in device wallets like Google Wallet and Apple Wallet. Your app requests the credential, the user consents, and Hopae Connect validates the cryptographically signed response.
When to use this integration:
  • Building a native mobile app (Android or iOS)
  • Building a web app that calls the DC API directly
  • Want the wallet request payload returned immediately (no QR scan or polling)
  • Verifying credentials from decentralized wallet providers (e.g., us-id-pass)

How it works

Your App                         Hopae Connect                    Device Wallet
  |                                   |                               |
  |  1. Create verification           |                               |
  |  POST /connect/v1/verifications   |                               |
  |---------------------------------->|                               |
  |  { verificationId, request }      |                               |
  |<----------------------------------|                               |
  |                                   |                               |
  |  2. Present request to wallet (on-device, no Hopae call)          |
  |-------------------------------------------------->                |
  |  signed credential                |                               |
  |<--------------------------------------------------|               |
  |                                   |                               |
  |  3. Submit credential             |                               |
  |  POST /gateway/.../callback       |                               |
  |---------------------------------->|                               |
  |  { status: success }              |                               |
  |<----------------------------------|                               |
  |                                   |                               |
  |  4. Retrieve verified identity    |                               |
  |  GET /verifications/{id}/userinfo |                               |
  |---------------------------------->|                               |
  |  { given_name, birthdate, ... }   |                               |
  |<----------------------------------|                               |
Your app makes 3 API calls to Hopae Connect. The wallet interaction (step 2) happens entirely on-device — Hopae is not involved.

Prerequisites

  • API credentials from the Console
  • A DC-enabled provider (e.g., us-id-pass) enabled for your app
  • Android: CredentialManager API (requires Google Play Services)
  • iOS: Safari 26+ with Digital Credentials API support
  • Web: Chrome 128+ with Digital Credentials API support

Implementation Steps

Step 1: Create Verification Session

Create a verification with options.mode = "native" to receive the wallet request payload immediately in the response.
curl -X POST https://sandbox.api.hopae.com/connect/v1/verifications \
  -u "CLIENT_ID:CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "providerId": "us-id-pass",
    "options": {
      "mode": "native",
      "platform": "android",
      "expected_origins": ["https://your-app-domain.com"]
    }
  }'

Options parameters

ParameterRequiredDescription
modeYesSet to "native" to receive the wallet request payload in the response. Without this, the payload is not returned.
platformYes"android" or "ios". Determines the VP request format — Android returns JSON (OpenID4VP), iOS returns binary CBOR (ISO mDOC).
expected_originsYesArray of origins your app presents credentials from. The wallet validates that the request originates from one of these before releasing the credential.

Response

{
  "verificationId": "f775c594fc9c4ac59848aac485862d71",
  "providerId": "us-id-pass",
  "status": "awaiting_user_action",
  "flowType": "dc",
  "flowDetails": {
    "request": {
      "protocol": "openid4vp-v1-unsigned",
      "data": {
        "response_type": "vp_token",
        "response_mode": "dc_api.jwt",
        "nonce": "13f16b12-a4b7-4d87-b654-41bb518e59d6",
        "client_id": "decentralized_identifier:did:web:...",
        "expected_origins": ["https://your-app-domain.com"],
        "dcql_query": { "..." : "..." },
        "client_metadata": { "..." : "..." }
      }
    },
    "dcSessionId": "13f16b12-a4b7-4d87-b654-41bb518e59d6"
  },
  "createdAt": "2026-06-03T15:22:42.404Z",
  "expiresAt": "2026-06-03T15:52:42.404Z",
  "verification_model": "disclosure"
}
When platform is "ios", the request.data contains deviceRequest and encryptionInfo (binary CBOR) instead of the JSON fields shown above.
The key field is flowDetails.request — pass this to the device wallet in step 2. The session expires after 30 minutes.

Step 2: Request Credential from Wallet

Pass flowDetails.request from step 1 to the W3C Digital Credentials API on your platform. This step happens entirely on-device — no Hopae API call is needed.
Use Android CredentialManager with GetDigitalCredentialOption:
val requestJson = Gson().toJson(flowDetails.request)
val option = GetDigitalCredentialOption(requestJson = requestJson)
val credentialRequest = GetCredentialRequest(listOf(option))

val result = credentialManager.getCredential(context, credentialRequest)
val responseString = result.credential.data.getString("response")
// Use responseString in step 3
The OS displays a consent screen showing which data is being requested. The user must approve before the credential is released.

Step 3: Submit Wallet Response

Send the signed credential response to Hopae Connect for validation.
curl -X POST https://sandbox.api.hopae.com/gateway/digital-credentials/callback \
  -H "Content-Type: application/json" \
  -d '{
    "sessionId": "f775c594fc9c4ac59848aac485862d71",
    "response": "eyJhbGciOiJFUzI1NiIs..."
  }'
ParameterDescription
sessionIdThe verificationId from step 1.
responseThe signed credential string from step 2.
This endpoint does not require authentication. The credential is validated cryptographically by the Verifier — signature verification, nonce binding, origin check, and trust chain validation against government issuer certificates. A forged or replayed credential is rejected regardless of the caller.
Success response:
{
  "status": "success",
  "data": {
    "family_name": "Garcia",
    "given_name": "Kelly",
    "birth_date": "1987-02-01",
    "sex": 2,
    "document_number": "D12345678",
    "issue_date": "2003-02-10",
    "expiry_date": "2052-02-10",
    "issuing_country": "XX",
    "issuing_authority": "Test Issuing Authority"
  },
  "sessionId": "f775c594fc9c4ac59848aac485862d71"
}

Step 4: Retrieve Verified Claims

Once the verification is complete, retrieve the normalized identity data with provenance.
curl -X GET https://sandbox.api.hopae.com/connect/v1/verifications/{verificationId}/userinfo \
  -u "CLIENT_ID:CLIENT_SECRET"
Response
{
  "sub": "LF4E9dRJylDBHJO7eKsIurVmVmt6tRA0",
  "provider_id": "us-id-pass",
  "verification_model": "disclosure",
  "hopae_loa": 4,
  "hopae_loa_label": "high",
  "amr": ["us-id-pass"],
  "user": {
    "source_id": "D12345678"
  },
  "missing_claims": [],
  "provenance": {
    "presentation": {
      "channel": { "type": "wallet", "transport": "internet" },
      "credentials": [
        {
          "type": "us-id-pass",
          "claims": {
            "given_name": "Kelly",
            "family_name": "Garcia",
            "birth_date": "1987-02-01",
            "sex": 2,
            "document_number": "D12345678",
            "issue_date": "2003-02-10",
            "expiry_date": "2052-02-10",
            "issuing_country": "XX",
            "issuing_authority": "Test Issuing Authority"
          },
          "issuer": {
            "authority_name": "US Digital ID Issuers",
            "is_government": true
          },
          "evidence": { "vpClaims": "..." }
        }
      ]
    },
    "_metadata": {
      "verification_id": "b93a6140a7f04c539789112503c5dcb0",
      "verified_at": "2026-06-03T15:50:48.672Z",
      "status": "completed"
    }
  }
}
Identity claims are available in provenance.presentation.credentials[].claims. The sub field is a stable pseudonymous identifier derived from the document number — consistent across verifications of the same document.

Error Handling

ScenarioStepError
Invalid credentials1, 4401 AUTH_INVALID_CREDENTIALS
Provider not enabled1400 PROVIDER_NOT_ENABLED
Provider doesn’t support native mode1400 PROVIDER_ERROR
Missing platform in native mode1400 VALIDATION_MISSING_PARAMETER
Invalid / tampered credential3{ status: "fail", code: "VERIFICATION_FAILED" }
Session expired3, 4400 SESSION_EXPIRED
Verification not found4404 SESSION_VERIFICATION_NOT_FOUND

Available Providers

Provider IDCredentialCountryPlatforms
us-id-passUS Digital Passport (ID PASS)USAndroid, iOS
More DC-enabled providers will be added. The integration flow is identical — only providerId changes.

Comparison with Standard API Flow

This guide is for native DC providers only. Most eID providers (BankID, MitID, Smart-ID, etc.) use the standard REST API integration with QR, redirect, or push flows. Use this guide only when integrating DC-enabled wallet providers listed above.
Standard API FlowDC Native Flow
ProvidersMost eIDs (QR, redirect, push)Wallet providers (DC API)
API calls2–3 + polling3 (no polling)
Wallet interactionHandled by Hopae web UIYour app calls DC API directly
Credential formatOAuth2/OIDC tokensW3C Verifiable Presentation
options.modeNot needed"native" required

Next Steps

Standard API Integration

For QR, redirect, and push flow providers

Verification API Reference

Full endpoint documentation

Return Data Model

Understanding user claims and provenance

Digital ID Types

Learn about wallet-based credentials