idcheck.now API Docs

Webhooks

Webhooks push verification outcomes to your server the moment they happen. Register an endpoint once; idcheck.now POSTs signed JSON events to it. Polling GET /v1/verifications/{id} works too, but webhooks are the recommended path.

Create an endpoint

POST/v1/webhooksscope webhooks:write

To register a webhook, POST /v1/webhooks with your HTTPS url and the events to subscribe to ("*" subscribes to everything). The response includes the endpoint secret used to verify delivery signatures — it is returned only here, at creation.

Request body

FieldTypeDescription
urlrequiredstring (URL)HTTPS endpoint that accepts POST. 10-second delivery timeout.
eventsrequiredstring[]Event names, or ["*"] for all events.
curl
curl -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"]}'
JavaScript
const res = await fetch("https://idcheck.now/v1/webhooks", {
  method: "POST",
  headers: { "X-Api-Key": process.env.IDCHECK_API_KEY, "Content-Type": "application/json" },
  body: JSON.stringify({ url: "https://yourapp.example/hooks/idcheck", events: ["verification.decided"] }),
});
const { id, secret } = await res.json(); // store secret — shown once
Python
import os, requests

res = requests.post(
    "https://idcheck.now/v1/webhooks",
    headers={"X-Api-Key": os.environ["IDCHECK_API_KEY"]},
    json={"url": "https://yourapp.example/hooks/idcheck", "events": ["verification.decided"]},
)
endpoint = res.json()  # store endpoint["secret"] — shown once
JSON201 Created
{
  "id": 4,
  "url": "https://yourapp.example/hooks/idcheck",
  "events": ["verification.decided"],
  "secret": "9f8e7d6c5b4a39281706f5e4d3c2b1a09f8e7d6c5b4a39281706f5e4d3c2b1a0",
  "active": true
}

List endpoints

GET/v1/webhooksscope webhooks:read

To list your webhook endpoints, GET /v1/webhooks. Secrets are never included.

JSON200 OK
[
  {"id": 4, "url": "https://yourapp.example/hooks/idcheck", "events": ["verification.decided"], "active": true}
]

Delete an endpoint

DELETE/v1/webhooks/{endpoint_id}scope webhooks:write

To stop deliveries, DELETE /v1/webhooks/{endpoint_id}. The endpoint is deactivated (soft delete) and the response is 204 No Content. Endpoints owned by another key return 404 webhook not found.

curl
curl -X DELETE https://idcheck.now/v1/webhooks/4 -H "X-Api-Key: $IDCHECK_API_KEY"

Event catalog

EventFired whenPayload (<code>data</code>)
verification.decidedA verification reaches status decided (at POST /v1/session/submit).{"decision": "approve|review|decline", "score": number, "reasons": string[]}

Subscribe with the exact event name or * for all current and future events. After receiving an event, fetch full details (checks, reasons, audit log) with GET /v1/verifications/{verification_id}.

Payload format

Deliveries are POST requests with a JSON body and two headers: Content-Type: application/json and X-IdCheck-Signature.

JSONDelivery body
{
  "event": "verification.decided",
  "verification_id": "b3f1c2a4-7d5e-4f6a-9c8b-1e2d3a4b5c6d",
  "data": {
    "decision": "approve",
    "score": 96.2,
    "reasons": []
  }
}

Verify signatures

Every delivery is signed with the endpoint secret. Header format: X-IdCheck-Signature: t=<unix_ts>,v1=<hmac_sha256_hex> where the HMAC input is "<t>.<raw_body>". Full verification code (Node.js + Python, constant-time comparison, replay-window check) is in Authentication → Webhook signatures.

JavaScript
// Express: capture the RAW body before JSON parsing
app.post("/hooks/idcheck", express.raw({ type: "application/json" }), (req, res) => {
  const ok = verifyIdCheckSignature(
    req.body.toString("utf8"),
    req.get("X-IdCheck-Signature"),
    process.env.IDCHECK_WEBHOOK_SECRET
  );
  if (!ok) return res.sendStatus(401);
  const { event, verification_id, data } = JSON.parse(req.body);
  if (event === "verification.decided") { /* fetch full verification, update user */ }
  res.sendStatus(200); // any 2xx marks the delivery as delivered
});
Python
# Flask: read the raw body, verify, then parse
from flask import Flask, request, abort

app = Flask(__name__)

@app.post("/hooks/idcheck")
def idcheck_hook():
    ok = verify_idcheck_signature(
        request.get_data(),
        request.headers.get("X-IdCheck-Signature", ""),
        os.environ["IDCHECK_WEBHOOK_SECRET"],
    )
    if not ok:
        abort(401)
    payload = request.get_json()
    if payload["event"] == "verification.decided":
        pass  # fetch full verification, update user
    return "", 200  # any 2xx marks the delivery as delivered

Retry policy

PropertyValue
AttemptsUp to 3 per delivery
Backoff between attempts0.5s, then 1.0s, then 2.0s
Per-attempt timeout10 seconds
Success criteriaAny response status < 300 marks the delivery delivered
ExhaustionDelivery marked failed; fetch the result via GET /v1/verifications/{id} instead
Respond fast, process async

Return a 2xx immediately and do the heavy work (API calls, DB writes) after responding. A slow handler eats the 10-second timeout and burns retry attempts.