Webhooks
Webhooks deliver application, decision, invitation, screening, fraud and operational events to your HTTPS endpoint.
Create an endpoint
Use Client Admin Portal → Developers or the entitled developer API. Choose only events your service handles. The signing secret is shown once.
Common events:
| Event | When it fires |
|---|---|
application.created | Application and invitation committed |
application.submitted | Applicant finished the permitted journey |
application.decided | Final approve/reject decision committed |
application.review_required | Policy or signal opened human work |
application.recovery_requested | Applicant selected an approved alternative collection route |
application.recovery_completed | Operator closed the recovery request as completed |
application.recovery_declined | Operator closed the recovery request as declined |
invitation.sent | Delivery provider accepted the message |
screening.match_detected | A screening candidate needs disposition |
fraud.alert_created | Transaction/account policy opened an alert |
The endpoint catalogue shown in your tenant is authoritative.
Verify before parsing
Read the exact raw request bytes. Compute HMAC-SHA256 over the documented timestamp/body envelope with the endpoint secret, then compare signatures in constant time.
import { createHmac, timingSafeEqual } from "node:crypto";
function verifyAssayraWebhook(
rawBody: Buffer,
timestamp: string,
receivedSignature: string,
secret: string,
) {
const ageSeconds = Math.abs(Date.now() / 1000 - Number(timestamp));
if (!Number.isFinite(ageSeconds) || ageSeconds > 300) return false;
const expected = createHmac("sha256", secret)
.update(`${timestamp}.`)
.update(rawBody)
.digest("hex");
const supplied = Buffer.from(receivedSignature, "hex");
const computed = Buffer.from(expected, "hex");
return (
supplied.length === computed.length && timingSafeEqual(supplied, computed)
);
}
Use the exact header names displayed by the Developer Hub/test-delivery record. Keep raw-body middleware ahead of JSON parsing.
Acknowledge quickly
- Verify signature and timestamp.
- Deduplicate the event/delivery ID.
- Persist the event durably.
- Return a
2xxresponse. - Process asynchronously and reconcile state through the API.
Do not hold the request open while provisioning an account or calling slow downstream systems.
Retries and rotation
Non-2xx delivery is retried with bounded backoff. Inspect attempts and response status in the delivery ledger. During secret rotation, accept the predecessor and successor only for the documented overlap, then remove the predecessor.
Never disable signature verification to fix a delivery problem.