Webhooks
Niftipay pushes partner-relevant events to the webhook URL configured on the
integration. Each delivery is a signed POST.
Verifying a webhook
Every delivery carries two headers you must check before trusting the body:
| Header | Meaning |
|---|---|
x-signature |
v1=<hex hmac-sha256(secret, "${x-timestamp}.${raw body}")> |
x-timestamp |
Unix seconds at send time |
x-webhook-id |
The id of the destination webhook |
Recompute hmac-sha256(secret, "<x-timestamp>.<raw request body>") and compare
it to the v1= value in x-signature. Reject mismatches, and reject timestamps
that fall outside a small clock-skew window. Always return 2xx quickly and
process asynchronously — a slow handler is retried as if it failed.
Event shape
{
"event_id": "evt_3f9a...",
"event_type": "payment.confirmed",
"created_at": "2024-01-01T00:00:00.000Z",
"partner_id": "client_abc123",
"data": {
"partner_customer_id": "pc_1",
"order_id": "1001",
"status": "paid"
}
}event_id is unique per delivery; use it to dedupe. The data field carries
only identifiers and status — never raw documents or PII. Re-read detail through
the API where scopes still apply.
The events Niftipay can emit today:
customer.updatedverification.pendingverification.approvedverification.rejectedagreement.accepteddocument.reviewedcapability.updatedpayment.confirmedpayment.expired
Retries
Failed deliveries are retried up to six times with exponential backoff:
1m, 5m, 25m, 2h, 10h, 24h. A 2xx response ends delivery; a non-retryable
4xx is dead-lettered; a 5xx or network timeout is retried on the schedule
above. Use event_id to dedupe across retries.
Webhooks are delivered only for the customers this partner onboarded, and only to destinations it supplied. A partner never receives another partner’s events.