idcheck.now API
Identity verification (KYC) for US businesses: driver's-license capture with AAMVA PDF417 barcode forensics, selfie + passive liveness, face matching, OFAC sanctions screening and duplicate-face fraud detection — behind one REST API and a 5-line JavaScript SDK.
What idcheck.now does
idcheck.now verifies a person's identity in under a minute. You create a verification
via the API, send your user through the hosted capture flow (or embed it with the
JavaScript SDK), and receive a scored decision —
approve, review or decline — by webhook or by polling.
- Document forensics — live in-browser PDF417 barcode decode plus an independent server-side re-decode; a mismatch between the two is a tamper signal. AAMVA CDS v01–v12, all 50 states. License-number recomputation checks for FL, IL and WI.
- Biometrics — face match between the license portrait and a live selfie (512-d embeddings, cosine similarity, threshold 0.6) and passive liveness detection (threshold 0.5).
- Compliance — OFAC SDN screening with fuzzy name matching and DOB corroboration, plus exact-match crypto wallet screening against SDN digital-currency addresses.
- Fraud — 1:N duplicate-face search: the same face under a different claimed identity is automatically declined.
- Auditability — every verification carries a hash-chained, tamper-evident event log you can retrieve with the decision.
Verification lifecycle
Every verification moves through a strict state machine. The client session endpoints drive the
user-facing states; the decision engine runs at submit.
Verifications expire 24 hours after creation (expires_at). The
client token that drives the hosted flow is valid for 30 minutes. See the
hosted flow reference for the full state machine and the decision
object.
Base URLs
| Purpose | URL |
|---|---|
REST API (all /v1/* endpoints) | https://idcheck.now |
| Hosted verification flow | https://idcheck.now/verify/{verification_id}?token={client_token} |
SDK hosted origin (default baseUrl) | https://verify.idcheck.now |
All API traffic is HTTPS + JSON. Request and response bodies are UTF-8 JSON unless stated otherwise. There is no separate sandbox origin yet — use a test-labelled API key while integrating.
Authentication
Two credential types, two audiences:
| Credential | Header | Used for |
|---|---|---|
API key (idc_…) | X-Api-Key: idc_… | Server-to-server calls: verifications, screening, keys, webhooks. Scoped (e.g. verifications:write). |
| Client token (opaque, 30-min TTL) | X-Client-Token: … (or Authorization: Bearer …) | The end-user's browser during the hosted flow: consent, document, selfie, submit, state. |
Webhooks are authenticated in the other direction: idcheck.now signs every delivery with
HMAC-SHA256 in the X-IdCheck-Signature header. Full details in
Authentication.
Quickstart
Five steps from zero to a scored identity decision. Everything below is plain curl — no SDK required.
-
Create an API key
From your bootstrap key (issued at onboarding), create a scoped working key. The plaintext key is returned exactly once — store it immediately.
curl201 Createdcurl -X POST https://idcheck.now/v1/keys -H "X-Api-Key: $BOOTSTRAP_KEY" -H "Content-Type: application/json" -d '{"label": "prod-backend", "scopes": ["verifications:write", "verifications:read", "webhooks:write"]}'JSON{ "id": 12, "label": "prod-backend", "scopes": ["verifications:write", "verifications:read", "webhooks:write"], "api_key": "idc_9fK2mVxQ8pLrT3nWsYbZcJhGdAeRuEiO7qN5sX0vM1k" } -
Create a verification
To create a verification,
POST /v1/verificationswith your API key. Pass your ownexternal_refso you can reconcile later. The response contains the hosted-flowurland aclient_token.curl201 Createdcurl -X POST https://idcheck.now/v1/verifications -H "X-Api-Key: $IDCHECK_API_KEY" -H "Content-Type: application/json" -d '{"external_ref": "user_4821", "user": {"email": "jane@example.com"}, "redirect_url": "https://yourapp.example/kyc/done"}'JSON{ "id": "b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d", "client_token": "x7Qp9m2LwR4tY8uZcVbN1sDfGhJkL0oP3eA5qW6rT2y", "url": "https://idcheck.now/verify/b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d?token=x7Qp9m2LwR4tY8uZcVbN1sDfGhJkL0oP3eA5qW6rT2y" } -
Send the user through the hosted flow
Open the returned
urlin a browser, or hand theclient_tokento the JavaScript SDK to render the flow in a modal:JavaScriptimport { createIdCheck } from '@idcheck/web'; const idcheck = createIdCheck({ publicKey: 'pk_test_...', sessionToken: clientToken }); idcheck.open();HTML<!-- zero-build alternative: just link the user to the hosted page --> <a href="https://idcheck.now/verify/b3f1c2a4-...?token=x7Qp9m2L...">Verify your identity</a>The user consents, photographs the front and back of their license, takes a selfie, and submits.
-
Get the decision — webhook or poll
Register a webhook once and idcheck.now POSTs
verification.decidedto your server (HMAC-signed):curlcurl -X POST https://idcheck.now/v1/webhooks -H "X-Api-Key: $IDCHECK_API_KEY" -H "Content-Type: application/json" -d '{"url": "https://yourapp.example/hooks/idcheck", "events": ["verification.decided"]}'Or poll the verification:
curlcurl https://idcheck.now/v1/verifications/b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d -H "X-Api-Key: $IDCHECK_API_KEY" -
Read the decision
The decision is one of
approve(score ≥ 80),review(50–79) ordecline(< 50), always with explainable reasons and per-signal scores.JSONGET /v1/verifications/{id} (truncated){ "id": "b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d", "external_ref": "user_4821", "status": "decided", "decision": "approve", "score": 96.2, "decision_reasons": [], "created_at": "2026-07-26T14:03:11.204512", "expires_at": "2026-07-27T14:03:11.204512" }