idcheck.now API Docs

Verifications

A verification is one identity-check session for one end user. Create it on your server, hand the client token or hosted URL to the user's browser, then read the decision. All four endpoints are merchant-authenticated with X-Api-Key.

Create a verification

POST/v1/verificationsscope verifications:write

To create a verification, POST /v1/verifications with an optional external_ref (your user's id), an optional free-form user object, and an optional redirect_url the hosted flow returns to when finished. The API creates the verification in status created (expires in 24 hours) and issues a 30-minute client_token for the hosted flow.

Request body

FieldTypeDescription
external_refoptionalstring | nullYour idempotency/reconciliation handle. Stored verbatim and returned on every read.
useroptionalobjectFree-form metadata about your user (e.g. email, internal id). Defaults to {}.
redirect_urloptionalstring | nullURL the hosted flow navigates to after completion (used by redirect-style integrations).
curl
curl -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"}'
JavaScript
const res = await fetch("https://idcheck.now/v1/verifications", {
  method: "POST",
  headers: { "X-Api-Key": process.env.IDCHECK_API_KEY, "Content-Type": "application/json" },
  body: JSON.stringify({
    external_ref: "user_4821",
    user: { email: "jane@example.com" },
    redirect_url: "https://yourapp.example/kyc/done",
  }),
});
const { id, client_token, url } = await res.json();
Python
import os, requests

res = requests.post(
    "https://idcheck.now/v1/verifications",
    headers={"X-Api-Key": os.environ["IDCHECK_API_KEY"]},
    json={
        "external_ref": "user_4821",
        "user": {"email": "jane@example.com"},
        "redirect_url": "https://yourapp.example/kyc/done",
    },
)
data = res.json()  # {"id": ..., "client_token": ..., "url": ...}

201 Created — response body

FieldTypeDescription
idrequireduuidVerification id. Use it for GET calls and to reconcile webhooks.
client_tokenrequiredstring30-minute token for the hosted flow (X-Client-Token). Deliver it to the browser.
urlrequiredstringFully-built hosted-flow URL ({HOSTED_BASE_URL}/verify/{id}?token=…). Redirect or link the user here.
JSON201 Created
{
  "id": "b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d",
  "client_token": "x7Qp9m2LwR4tY8uZcVbN1sDfGhJkL0oP3eA5qW6rT2y",
  "url": "https://idcheck.now/verify/b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d?token=x7Qp9m2LwR4tY8uZcVbN1sDfGhJkL0oP3eA5qW6rT2y"
}
Client token lifetime

The client token expires after 30 minutes while the verification itself lives 24 hours. If a user abandons the flow and returns later, create a new verification — do not try to reuse a stale token.

List verifications

GET/v1/verificationsscope verifications:read

To list your verifications, GET /v1/verifications. Results are scoped to the calling API key, newest first. Use status to filter by lifecycle state.

Query parameters

FieldTypeDescription
limitoptionalinteger (query)Page size, 1–200. Default 50.
offsetoptionalinteger (query)Rows to skip. Default 0.
statusoptionalstring (query)Filter by exact status, e.g. decided.
curl
curl "https://idcheck.now/v1/verifications?status=decided&limit=25" -H "X-Api-Key: $IDCHECK_API_KEY"
JavaScript
const res = await fetch("https://idcheck.now/v1/verifications?status=decided&limit=25", {
  headers: { "X-Api-Key": process.env.IDCHECK_API_KEY },
});
const { total, items } = await res.json();
Python
import os, requests

res = requests.get(
    "https://idcheck.now/v1/verifications",
    headers={"X-Api-Key": os.environ["IDCHECK_API_KEY"]},
    params={"status": "decided", "limit": 25},
)
page = res.json()  # {"total", "limit", "offset", "items": [...]}
JSON200 OK
{
  "total": 137,
  "limit": 25,
  "offset": 0,
  "items": [
    {
      "id": "b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d",
      "external_ref": "user_4821",
      "status": "decided",
      "decision": "approve",
      "score": 96.2,
      "created_at": "2026-07-26T14:03:11.204512",
      "expires_at": "2026-07-27T14:03:11.204512"
    }
  ]
}

Retrieve a verification

GET/v1/verifications/{verification_id}scope verifications:read

To retrieve a verification — including the full decision, every document check, the consent record and the hash-chained audit log — GET /v1/verifications/{verification_id}. Verifications belonging to a different API key return 404 verification not found (never 403 — existence is not leaked).

curl
curl https://idcheck.now/v1/verifications/b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d -H "X-Api-Key: $IDCHECK_API_KEY"
JavaScript
const res = await fetch(
  "https://idcheck.now/v1/verifications/b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d",
  { headers: { "X-Api-Key": process.env.IDCHECK_API_KEY } }
);
const verification = await res.json();
Python
import os, requests

res = requests.get(
    "https://idcheck.now/v1/verifications/b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d",
    headers={"X-Api-Key": os.environ["IDCHECK_API_KEY"]},
)
v = res.json()
print(v["decision"], v["score"], v["decision_reasons"])
JSON200 OK (truncated events)
{
  "id": "b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d",
  "external_ref": "user_4821",
  "status": "decided",
  "decision": "approve",
  "score": 96.2,
  "created_at": "2026-07-26T14:03:11.204512",
  "expires_at": "2026-07-27T14:03:11.204512",
  "decision_reasons": [],
  "checks": {
    "doc_checks": {
      "mandatory_elements": {"passed": true, "missing": []},
      "not_expired": {"passed": true, "expiry": "2029-04-17"},
      "license_recompute": {"passed": true, "skipped": "state_not_supported_or_no_dob"},
      "server_client_barcode_match": {"passed": true},
      "ofac": {"matched": false, "confidence": "none", "score": 0.412},
      "face_dedupe": {"matches": [], "impact": null, "reason": "no_matches"}
    },
    "face_match_score": 0.91,
    "liveness_score": 0.88,
    "license_fields": {
      "last_name": "DOE",
      "first_name": "JANE",
      "middle_name": null,
      "date_of_birth": "1990-06-15",
      "age": 36,
      "expiry": "2029-04-17",
      "license_number": "D1234567",
      "street": "123 MAIN ST",
      "city": "PITTSBURGH",
      "state": "PA",
      "zip": "15201",
      "sex": "female"
    }
  },
  "consent": {
    "bipa": true,
    "recording": true,
    "policy_version": "2026-07-01",
    "captured_at": "2026-07-26T14:04:02.117300",
    "ip": "203.0.113.44",
    "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 19_0 like Mac OS X)"
  },
  "events": [
    {
      "seq": 1,
      "actor": "merchant",
      "action": "session.created",
      "payload": {"external_ref": "user_4821"},
      "ip": "198.51.100.9",
      "event_hash": "b7f2a1c9d4e3f6a5b8c7d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1",
      "created_at": "2026-07-26T14:03:11.210044"
    }
  ]
}

Beyond the summary fields, the response adds decision_reasons, a checks object (doc_checks, face_match_score, liveness_score, license_fields), the consent record, and events — the ordered, hash-chained audit trail. Every check id in doc_checks is explained in the decision object reference.

Get verification media

GET/v1/verifications/{verification_id}/mediascope verifications:read

To download the captured images, GET /v1/verifications/{id}/media. The media bucket is private — the only access path is the short-lived presigned URLs returned here. Links expire after 3600 seconds (1 hour); call the endpoint again for fresh links. Every issuance is audit-logged as media.links_issued. In local-fallback deployments without S3, url and expires_in are null.

curl
curl https://idcheck.now/v1/verifications/b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d/media -H "X-Api-Key: $IDCHECK_API_KEY"
JavaScript
const res = await fetch(
  "https://idcheck.now/v1/verifications/b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d/media",
  { headers: { "X-Api-Key": process.env.IDCHECK_API_KEY } }
);
const { media } = await res.json();
for (const [side, info] of Object.entries(media)) console.log(side, info.url);
Python
import os, requests

res = requests.get(
    "https://idcheck.now/v1/verifications/b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d/media",
    headers={"X-Api-Key": os.environ["IDCHECK_API_KEY"]},
)
for side, info in res.json()["media"].items():
    print(side, info["url"], info["sha256"])

200 OK — response body

FieldTypeDescription
mediarequiredobjectMap of media side → object. Keys: front, back, selfie, selfie_frame_0selfie_frame_7 (whichever were captured).
media.<side>.keyrequiredstringStorage object key.
media.<side>.sha256requiredstringSHA-256 of the stored bytes — verify downloads against it.
media.<side>.urlrequiredstring | nullPresigned GET URL (SigV4). Null when storage is in local-fallback mode.
media.<side>.expires_inrequiredinteger | nullSeconds the URL remains valid (3600).
JSON200 OK
{
  "media": {
    "front": {
      "key": "b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d/front-9ab3c4d5e6f70819.jpg",
      "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
      "url": "https://s3.us-east-1.amazonaws.com/idcheck-media/b3f1c2a4-.../front-9ab3c4d5....jpg?X-Amz-Signature=…",
      "expires_in": 3600
    },
    "selfie": {
      "key": "b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d/selfie-1a2b3c4d5e6f7788.mp4",
      "sha256": "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
      "url": "https://s3.us-east-1.amazonaws.com/idcheck-media/b3f1c2a4-.../selfie-1a2b3c4d....mp4?X-Amz-Signature=…",
      "expires_in": 3600
    }
  }
}

The verification object

Summary shape returned by the list endpoint and embedded in every verification response:

Verification summary fields

FieldTypeDescription
idrequireduuidVerification identifier.
external_refoptionalstring | nullYour own reference, echoed back.
statusrequiredstringLifecycle state: created, consented, doc_front, doc_back, selfie, submitted, processing, decided.
decisionrequiredstring | nullapprove | review | decline; null until decided.
scorerequirednumber | nullComposite score 0–100. Bands: ≥ 80 approve, 50–79 review, < 50 decline.
created_atrequiredISO 8601Creation timestamp.
expires_atrequiredISO 8601Creation + 24 hours.

The decision fields (decision, score, decision_reasons) are populated when the user submits and the decision engine runs — see the decision object for scoring, bands and every reason string.