Webhooks and recovery

Webhooks are the expected path for receiving verification completion and the rare later status change. A webhook integration does not need to poll GET /v1/events during normal operation.

Configure destinations

Configure both destinations with PUT /v1/webhook-endpoints, which replaces the complete pair. Set either value to null to disable that stream. The configuration is shared across your verifications. Use GET /v1/webhook-endpoints when you want to read the current configuration; it is not a required setup step.

When you configure a destination, ZeroAge sends a challenge to that endpoint. Your endpoint uses your webhook verification secret to produce the challenge response. A correct response confirms that you control the endpoint. Keep the secret on your backend.

Destination Event
verification_completed_url verification.completed: one logical event for each terminal request, including cancelled and expired requests whose result is unsure
verification_status_changed_url verification.status_changed: a later material change to the current assessment

Delivery can repeat an event or deliver events out of order. A later material change has a new revision; unchanged reassessment does not produce an event.

Receive events

The data field is a full base Verification snapshot at that revision. It excludes the sensitive handoff URL, app capabilities, signatures, proofs, and evidence. See the Quickstart and API reference for complete JSON examples.

  1. Validate the event schema and require verification_id == data.id and revision == data.revision before starting business processing.
  2. Deduplicate durably by event id. Acknowledge an identical duplicate. If the same ID has conflicting content, stop processing and reconcile; never overwrite the saved event.
  3. Save the event durably before returning HTTP 200, 204, or another 2xx response, then process it asynchronously. Apply the Results and revisions revision rules; reconcile conflicting original decisions without overwriting original. Commit the state update and job enqueue atomically. Make business effects idempotent.
  4. Resume queued work after a worker restart.

A 2xx response marks the event as received. It does not mean that downstream business processing has completed.

ZeroAge retries automatically after a timeout or non-2xx response, with increasing delays. Every attempt for one logical event uses the same event ID and payload, so keep the duplicate and ordering safeguards above.

Optional event feed

GET /v1/events is an optional recovery and troubleshooting tool, and an alternative for customers that choose polling instead of webhooks. Webhook users do not need to poll it routinely.

  1. Call GET /v1/events; omit after on the first request. Treat every returned cursor as opaque and keep each customer’s credentials, events, and cursor separate.
  2. If you use the feed, save all events durably before advancing to next_cursor. If has_more is true, request the next page immediately. Otherwise retain that cursor for the next poll, including when the page is empty.
  3. Reconcile uncertain state with GET /v1/verifications/{id}. If local delivery may be stale, read the current Verification before a consequential action.
  4. Apply the same revision and original-decision rules used for webhook delivery.