SCROLL
UK→US  ·  IN→US  ·  KE→US  ·  Portable credential protocol Groth16 + Ed25519 Verifier API UK→US  ·  IN→US  ·  KE→US  ·  Portable credential protocol Groth16 + Ed25519 Verifier API
Developer docs
Running pilots now

Integrate in hours, not months.

One endpoint. One API key. Verified credential claims returned in milliseconds. Production-ready in hours — with institutions staying fully in control of decisions.

From zero to verified in 3 steps.

Drop in one React component. A QR code appears on your page. Your customer scans it in the PASSID app. Proven claims land in your onSuccess callback — automatically. No token copying, no manual steps.

① Install the SDK and drop in one component

Install @passid/react and drop <PASSIDVerify /> anywhere in your application. Your institution API key is your only configuration. The component handles QR generation, deep-link creation, polling, countdown timer, and all UI states.

No backend changes — zero server code to write
QR rendered locally via qrcode canvas — no third-party image service
8-char fallback code shown for in-branch / accessibility use
Request auto-expires in 10 min — component shows live countdown
your-app.jsx YOUR APP
// terminal
npm install @passid/react

// your loan application page
import { PASSIDVerify } from "@passid/react";

<PASSIDVerify
  apiKey="live_abc123..."
  institutionName="First National Bank"
  permissions={[
    "income_verified",
    "full_score",
    "sanctions_clear"
  ]}
  onSuccess={(claims) => {
    // claims arrive automatically
    approveLoan(claims.fsi_score);
  }}
/>

Endpoints

All endpoints require X-Institution-Key: <your-api-key> unless marked public. Base URL: https://api.passid.io

SDK / QR Verification Flow
POST
/api/bridge/request
Create a verification session
Called automatically by <PASSIDVerify /> on mount. Returns requestId, code (e.g. AB3X-7YQM), deepLink (passid://verify-request?r=…&i=…), and expiresAt. Body: { institutionName?, permissions?, ttlSeconds? } — TTL defaults to 600 s, max 3600 s.
GET
/api/bridge/request/:requestId
Poll for completion
SDK polls this every 2.5 s after creating a request. Returns status: "pending" | "completed" | "declined" | "expired". When completed, response includes the full claims object and verifiedAt. Requires institution API key.
GET
/api/bridge/request/:id/public
NO AUTH
Public request info (mobile app)
Called by the PASSID mobile app after scanning a QR — no institution API key needed. Returns institution name, requested permissions, and seconds until expiry. Returns 410 if already expired, fulfilled, or declined.
GET
/api/bridge/request/by-code/:code/public
NO AUTH
Resolve 8-char fallback code
Resolves the human-readable code (e.g. AB3X-7YQM or AB3X7YQM) to the same response as the public request endpoint. Used by the in-app manual code entry screen.
Direct Token Verification
POST
/api/bridge/verify
Verify a PASSID token
Accepts a PASSID share token directly. Returns { valid, claims, analytics?, denyReason? }. Used by the SDK's manual entry path and by the institution dashboard "New Verification" screen. Pass Idempotency-Key header — retries never double-verify. Response includes X-PASSID-API-Version: 1.
Outcome Reporting
POST
/api/bridge/outcome
Report a loan outcome
Report what happened after a PASSID-verified decision — weeks or months later. Body: { token, outcome, productType?, amountUsd?, observationDays?, notes? }. Valid outcomes: repaid · no_default · delinquent · defaulted · fraud_confirmed · account_closed · other. The FSI score at time of verification is captured automatically — you never send it. One outcome per token per institution. Fires outcome.reported webhook.
GET
/api/bridge/outcome/cohort
Your cohort calibration data
Returns default rate and repay rate broken down by FSI tier (A/B/C/D) for all outcomes your institution has reported. Shown on your institution performance dashboard. Requires institution JWT.
Auth
POST
/api/institution/token/refresh
Refresh session token
Exchange a 30-day refresh token for a new access token + rotated refresh token. Enables long-lived sessions without re-authentication. Reuse of a consumed token triggers automatic revocation of the entire token family.
GET
/api/v1
API version discovery
Returns the current API version, model version (1.0.0), release date, and a full map of all endpoint paths. Use to confirm your integration is on the versioned surface.

Event-driven verification.

verification.completed
Fires immediately after a token is successfully verified. Includes all proven claims, proof type, and expiry. Safe to retry — use Idempotency-Key on the verify call to prevent duplicate webhooks.
verification.failed
Fires when a token is rejected — expired, revoked, or institution mismatch. Includes deny_reason string. Only fired when the request carries a valid institution API key.
outcome.reported
Fires when an institution submits a loan outcome via POST /api/bridge/outcome. Payload includes the token, outcome type, product type, amount, and the FSI score that was used at decision time. Use for audit trails and downstream model updates.
webhook.test
Manual ping from your dashboard to confirm your endpoint is reachable. Use to validate signature verification before going live.
Delivery: HMAC-SHA256 signed via X-PASSID-Signature: sha256=<hex>. Automatic retries on non-2xx: immediate → 30 s → 5 min → 30 min → 2 h (5 attempts total). Pending deliveries survive server restarts.
Webhook payload — verification.completed · X-PASSID-Signature: sha256=…
{
  "event": "verification.completed",
  "institution_id": "42",
  "timestamp": "2026-03-27T10:22:14Z",
  "data": {
    "token": "pid_K3px...",
    "verified_at": "2026-03-27T10:22:14Z",
    "proof_type": "groth16/bn254",
    "claims": { "tier": "B", "fsi_score": 801, "income_verified": true, "sanctions_clear": true }
  }
}

Test without production data.

Use your sandbox API key with the same endpoints. The sandbox returns deterministic results — identical API shape to production, isolated from live data.

Live sandbox tokens — pre-seeded in the API, ready to verify now
Use these exact strings with POST /api/bridge/verify · { "token": "PASSID-SANDBOX-..." }
TIER A · KE→GB · Score 812
PASSID-SANDBOX-TIER1AAA
Amara Osei · income ✓ · identity ✓ · sanctions clear · fraud low · approved
TIER B · NG→US · Score 743
PASSID-SANDBOX-TIER2BBB
Tobenna Eze · income ✓ · identity ✓ · sanctions clear · fraud low · approved
TIER C · GH→EU · Score 671
PASSID-SANDBOX-TIER3CCC
Efua Mensah · income ✓ · identity ⚠ unverified · fraud medium · review
Permission Values — pass in permissions[] array
full_scoreFSI score, tier, confidence interval, p_stable
income_verifiedBoolean + income band (e.g. $3,000–$4,000/mo)
identity_verifiedIdentity verification boolean
sanctions_clearOFAC · EU · UN watchlist check result
payment_reliability0–1 score: on-time payment consistency
savings_consistency0–100 score: savings balance regularity
fraud_risklow · medium · high — synthetic fraud signal
Synthetic profiles
3 pre-seeded sandbox tokens (above) covering Tier A/B/C, approved and review states. Call POST /api/bridge/verify with the exact token string — live in the API now.
Webhook simulator
Trigger verification.completed, verification.failed, and outcome.reported test events from your institution dashboard → API & Webhooks panel.