Skip to main content

Webhooks

Webhooks deliver real-time notifications to your system when verification events occur. Instead of polling for results, configure a webhook endpoint and Zenoo will POST event payloads as they happen.

Events

Setup

1

Provide your endpoint URL

During onboarding, give Zenoo the HTTPS URL where you want to receive events:
2

Receive your webhook secret

Zenoo generates an HMAC secret for signature verification. Store it securely (environment variable, secrets manager).
3

Implement signature verification

Every webhook includes an X-Zenoo-Signature header. Verify it before processing any payload:
server.js
4

Return 200 within 30 seconds

Your endpoint must respond with a 200-299 status code within 30 seconds. If it does not, Zenoo treats the delivery as failed and retries.
Process events asynchronously. Accept the webhook, store the payload, and handle business logic in a background job.

Payload Structure

All webhook events share this envelope:
The callback_reference echoes back the value you set when initiating the verification. Use it to correlate webhook events with records in your system.

Event Payloads

verification.completed

Fires when a Person or Company Verification journey completes. The data field contains the full verification results, identical to the pull endpoint response.

screening.completed

Fires when standalone screening completes.

journey.abandoned

Fires when a user closes the verification UI or navigates away without completing it.

journey.expired

Fires when the 24-hour verification URL expires before the user completes the flow.

check.failed

Fires when a check fails after all automatic retry attempts are exhausted. This is a terminal state.
Do not retry the same check after receiving this event. Investigate the cause (invalid data, provider outage, missing information) and either correct the issue or escalate.

Retry Logic

If your endpoint does not return 200-299 within 30 seconds, Zenoo retries with increasing delays: After 7 days of consecutive failures, the webhook is marked as undeliverable. Contact Zenoo support to replay failed events.

Idempotency

Your webhook handler must be idempotent. Zenoo may deliver the same event more than once in edge cases (network timeouts, retry storms).
Use journey_id combined with event_type as a deduplication key to prevent processing the same event twice.
server.js
Always return 200 for duplicate events. Returning an error causes unnecessary retries.

Error Handling

How Zenoo responds to your endpoint’s status codes:
Return 200 OK immediately, then process the event in a background job. This is the single most important implementation detail for reliable webhook handling.

Testing

Staging Webhooks

Configure your staging webhook endpoint during onboarding. All verification flows in the staging environment trigger the same webhook events as production, using mock provider data.

Local Development

Use a tunneling tool to expose your local server:

Webhook Replay

Contact Zenoo support to replay specific webhook events. This is useful for:
  • Debugging payload parsing issues
  • Testing idempotency handling
  • Recovering from endpoint downtime

Security Checklist

  • Verify X-Zenoo-Signature on every incoming webhook
  • Use HTTPS for your webhook endpoint (no plain HTTP)
  • Respond with 200 within 30 seconds
  • Handle duplicate deliveries (idempotent processing)
  • Log failed signature verifications as security events
  • Process event payloads asynchronously (queue + worker)
  • Allowlist Zenoo IP ranges in production firewalls
Never skip signature verification. Without it, your endpoint accepts forged requests from anyone who knows your URL.

Signature Verification

Zenoo signs all outbound webhook payloads using HMAC-SHA256. Every webhook request includes a signature in the X-Zenoo-Signature header. Verify this signature before processing the payload.

Signature format

The value is a sha256= prefix followed by the hex-encoded HMAC-SHA256 digest of the raw request body, computed with your webhook secret.

Verification steps

1

Extract the signature header

Extract the X-Zenoo-Signature header value from the incoming request.
2

Isolate the hex digest

Remove the sha256= prefix to isolate the hex digest.
3

Compute the expected digest

Compute HMAC-SHA256 of the raw request body using your webhook secret.
4

Compare using constant-time comparison

Compare the computed digest with the received digest using a constant-time comparison function. If the digests do not match, reject the request with 401 Unauthorized. Do not process the payload.

Code examples

Express does not provide req.rawBody by default. Use the body-parser middleware with verify option or express.raw() to capture the raw body before JSON parsing:

Constant-time comparison

Always use a constant-time comparison function when verifying signatures. Standard string equality operators (==, ===, .equals()) are vulnerable to timing attacks. An attacker can measure response times to incrementally guess the correct signature byte by byte.

JWT-encoded webhooks

Some webhook configurations deliver payloads as JWT tokens instead of raw JSON. Zenoo auto-detects the format:
  • If the request body starts with eyJ and contains exactly 3 dot-separated segments, it is treated as a JWT.
  • The JWT payload is decoded and verified against your webhook secret.
  • Your verification logic does not need to change. Zenoo handles the decoding transparently.
You do not need to configure anything to enable or disable JWT encoding. The detection is automatic.

Handling verification failures

When signature verification fails:
  1. Reject the request with 401 Unauthorized.
  2. Log the failure with the request timestamp, source IP, and headers.
  3. Do not process the payload.
  4. Monitor for repeated failures, which may indicate an attack or a misconfigured secret.
If every webhook fails verification, check that your webhook secret matches the one Zenoo provided during onboarding. Secrets are environment-specific. A staging secret will not validate production webhooks.

Next Steps

Error Handling

Handle API failures and retries

Result Delivery

Compare push, pull, and ping+pull models

Idempotency

Prevent duplicate verifications

Testing & Sandbox

Test webhook delivery in staging