Overview
Verify is a SaaS platform for verifying digital IDs (mDLs, ePassports) in web applications. The Verify SDK lets you add verification to your site with a few lines of code — the SDK handles wallet communication, protocol negotiation, and the verification UI through a hosted iframe. You get back structured, cryptographically verified identity data.
How it works
Section titled “How it works”The SDK has a split architecture. Two functions run on your backend (where your API key lives), and two run in the browser (where the user interacts with the verification UI):
Your Backend ──(API key)──► Verify API │ ▲ │ session data │ ▼ │Your Frontend ──(postMessage)──► Verify IframeThe verification flow has six steps:
- Your backend creates a session — calls
fetchSessionData()with your API key. Returns a session ID, a short-lived client secret, and the iframe URL. - Your frontend initializes the session — calls
initVerificationSession()with the session data from your backend. Returns a session object. - Your frontend launches verification — calls
session.launchMdlVerification(), which injects an iframe into a<div>on your page. The iframe guides the user through wallet type and jurisdiction selection. - The user shares their credential — via the Digital Credentials API (same-device, browser-native), or through pre-defined protocols based on their wallet (cross-device QR code scan, deep link, etc.). The SDK detects browser support and selects the best available flow automatically.
- The iframe signals completion — the promise from
launchMdlVerification()resolves, and the iframe is removed from the DOM. - Your backend fetches results — calls
fetchSessionResults()with the session ID and your API key. Returns verified identity data organized by namespace.
What the SDK handles for you
Section titled “What the SDK handles for you”You don’t need to implement any of the following — the SDK and hosted infrastructure manage it:
- Protocol negotiation (OID4VP, Digital Credentials API)
- Wallet communication and credential exchange
- Credential decryption (ECDH-ES, HPKE)
- Issuer signature validation (ECDSA P-256)
- Certificate chain verification (IACA trust anchors)
- Certificate revocation checking
- Session state and lifecycle (10-minute TTL, single-use)
- Verification UI (wallet selection, QR code display, success/error screens)
Prerequisites
Section titled “Prerequisites”API key
Section titled “API key”You need an API key in the format verify_... to authenticate with the Verify API. Email support@spruceid.com to request access.
Backend
Section titled “Backend”The SDK requires a server-side component. fetchSessionData() and fetchSessionResults() both take your API key and must run on your backend — never in the browser. Any backend language or framework works. The SDK provides TypeScript helpers, but the underlying HTTP API can be called directly from any language (see the HTTP API guide for details).
Browser support
Section titled “Browser support”The SDK supports two verification flows, and automatically selects the best one available:
- Digital Credentials API (same-device): Chrome 128+ on Android with Google Wallet, Safari 18+ on iOS/macOS with Apple Wallet. The browser natively prompts the user’s wallet app.
- QR code / deep link flow (cross-device): Works in any modern browser. The user scans a QR code or taps a link on a separate mobile device with a compatible wallet.
The iframe requires standard postMessage support and the digital-credentials-get permissions policy. HTTPS is required in production for the Digital Credentials API; localhost works for development.
Supported wallets and jurisdictions
Section titled “Supported wallets and jurisdictions”The SDK currently supports verification from:
- Apple Wallet (iOS)
- Google Wallet (Android)
- State-issued wallets, e.g., CA DMV Wallet (iOS / Android)
For mDLs, many US jurisdictions are supported, with the list expanding regularly. ePassport support is also available. The iframe handles wallet and jurisdiction selection, and the list is updated automatically as support expands. Jurisdictions can be filtered at session creation time (see Jurisdiction filtering for details).
See the Wallet compatibility guide for full details on per-jurisdiction support and browser requirements.
Security model
Section titled “Security model”API key isolation
Section titled “API key isolation”Your API key authenticates your tenant with the Verify service. It is only accepted by fetchSessionData() and fetchSessionResults() — both of which should only run on your backend. The SDK does not provide any way to use the API key from the browser.
Client secret
Section titled “Client secret”Each session generates a short-lived client secret (10-minute TTL). It is safe to pass to the browser — it is scoped to a single session and cannot be used to create new sessions or access other tenants’ data.
Iframe isolation
Section titled “Iframe isolation”The verification UI runs in a cross-origin iframe hosted by SpruceID. Your page and the iframe communicate only via structured postMessage calls with origin validation. Your page never handles raw credential data — the verified result is only available through your backend via fetchSessionResults().
Credential verification
Section titled “Credential verification”All cryptographic verification is performed server-side by the Verify API:
- Issuer certificate chain validation against IACA trust anchors
- ECDSA signature verification
- Certificate revocation checking (CRL)
- Session transcript binding (prevents replay attacks)
Your application receives the verified outcome. You do not need to implement any cryptography.
Trust anchor
Section titled “Trust anchor”If your wallet requires a root CA in its trust store to accept verification requests from Verify, use the certificate available at the following URL. This is the root CA for the Verify service’s IACA certificate chain.