Keys
- Secrets live in a secret manager or environment variables, never in source control.
- A separate key per service, so one can be revoked without taking everything down.
- Scopes trimmed to what each service actually calls.
- IP allowlist set if your egress addresses are stable.
- If a key has an expiry, there is a calendar reminder to roll it before it lands.
- Someone owns the rotation runbook and knows where the secret is stored.
Details in Authentication.
Webhooks
This is where most production incidents start. Work through all of it.
- Your endpoint verifies the signature against the raw request body.
- The signing secret is base64-encoded before being handed to your Standard Webhooks library, or you use the SDK's
verifyWebhookSignaturehelper, which does it for you. - The private key shown once when the webhook was created is stored in configuration and passed as the fourth argument to
verifyWebhookSignature. Payloads are encrypted, so without it an encrypted delivery throws instead of returning a readable payload. - Handlers are idempotent, keyed on
webhook-idor on verification ID plus event. - You return
2xxquickly and queue the slow work rather than doing it inline. - You do not assume event ordering;
occurred_atguards against stale overwrites. - Signature failures return
400, never2xx. - The endpoint is reachable from the public internet and its TLS certificate is valid.
Remember that a delivery is abandoned after 12 failed attempts, about eight days. An endpoint that is down longer than that loses those events, so reconcile with GET /v1/verifications/:id rather than relying on retries. See Webhooks.
Failure handling
- Retries are limited to
429and5xx, with backoff and a cap. external_idis generated and persisted before the create call, so retries don't duplicate sessions.- Client timeouts are set explicitly, with more headroom on extraction and face-match calls.
- You have decided what your product does when verification is unavailable: queue, degrade, or block. Decide it now, not during an incident.
See Errors.
Verdict handling
Make sure every branch is actually implemented, not just the happy path:
- On
auto_approvedandmanual_approved, let the user through. - On
auto_rejectedandmanual_rejected, take your rejection path, with something useful to tell the user. verification:manual_requiredmeans the session is with a reviewer. This is not a final answer. Your UI needs a "we're checking" state, and your data model needs somewhere to park it.- Sessions that are never completed, because users abandon flows. Decide how long you wait and what happens then.
Expired sessions are a normal outcome, not an error. expires_at on the create response tells you when; create a fresh session rather than reusing a stale URL.
Data hygiene
- Request and response bodies for verification and extraction calls are excluded from your logs, because they contain identity documents and face images.
- API secrets never appear in logs, error reports, or URLs.
- Your privacy policy and retention schedule cover verification data, and you know which of you is the controller for it.
- You have a path to honour a deletion request from an end user.
Monitoring
- Alert on webhook handler error rate and on processing latency, not just on uptime.
- Alert on verifications created but never completed, past your abandonment threshold.
- Watch the manual review queue, because nothing tells you it is backing up except the queue itself.
- Subscribe to Service Status.
Rolling out
Put a small slice of real traffic through first, an internal cohort or a single low-volume market, and watch the verdict distribution before widening. An unexpectedly high rejection rate usually means a policy threshold is too tight or the capture UX is failing on a device you didn't test, and both are far cheaper to find at 1% than at 100%.
Keep a way to turn verification off. A feature flag that falls back to your previous flow is worth having before you need it.
Before you flip the switch
If you want a second pair of eyes on the integration, email contact@idproval.com or see Business support. We would rather look at it beforehand than debug it with you afterwards.