Documentation Index
Fetch the complete documentation index at: https://docs.zafapay.com/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Webhooks allow you to receive real-time notifications for payment events such as completion, failure, and refunds. ZAFA PAY sends HTTP POST requests to your registered webhook endpoints when payment status changes.Webhook endpoints can be managed from the Webhooks tab in the merchant dashboard (https://app.zafapay.com). Each endpoint has its own Webhook Secret for signature verification.
Webhook Endpoints
You can register multiple webhook endpoints to receive event notifications. Each endpoint has its own URL, secret, and optional event filter.| Feature | Description |
|---|---|
| Multiple endpoints | Register up to 16 webhook endpoints per merchant |
| Event filtering | Choose which event types each endpoint receives. If no filter is set, the endpoint receives all events |
| Per-endpoint secrets | Each endpoint has its own Webhook Secret (whsec_xxx format) for signature verification |
| Enable/disable | Endpoints can be individually activated or deactivated without deletion |
Event Types
| Event | Description |
|---|---|
payment.succeeded | Payment completed successfully |
payment.failed | Payment failed |
payment.canceled | Payment canceled — either voided by the merchant (POST /v1/payments/{id}/void) or canceled by the customer during 3D Secure authentication on the hosted checkout page |
payment.refunded | Refund completed |
payment.chargeback | Chargeback occurred |
Payload
Event type (e.g.,
payment.succeeded)Transaction ID
Merchant ID
Merchant name
Payment status (
succeeded, failed, canceled, refunded, chargeback)Payment amount (string format, e.g.,
"100.00")Currency code
Payment method (
card, depot, etc.)Saved card ID (
pmi_xxx format). Only included for recurring payments or when save_card was usedtrue for recurring (subscription) paymentsOnly included as
true when the card was saved for future useMerchant’s order ID (the value specified when creating the payment)
Product name (the value specified when creating the payment)
Customer ID (the value specified when creating the payment)
Customer’s email address (the value specified when creating the payment)
Customer’s phone number (the value specified when creating the payment)
Refunded amount (string format.
payment.refunded event only)Error details (
payment.failed event only)Card brand (
visa, mastercard, amex, jcb, etc.)Last 4 digits of the card number
Cardholder name
Card expiration month
Card expiration year
Card issuing country (ISO 3166-1 alpha-2 code, e.g.,
US, JP, SG). Only included when BIN lookup data is available.Card funding type (
credit, debit, prepaid). Only included when BIN lookup data is available.Metadata specified when creating the payment
Transaction creation timestamp (ISO 8601 format)
Webhook sent timestamp (ISO 8601 format)
Payload Examples
payment.succeeded (Payment Successful)
payment_method_idis only included whensave_cardwas used or for recurring paymentssave_cardis only included astruewhen the card was saved in the initial paymentis_recurringistruefor recurring payments
payment.failed (Payment Failed)
The
error object is only included in payment.failed events. Use recommended_action to determine the appropriate response (retry, contact_customer, use_different_card, or none).payment.canceled (Payment Canceled)
payment.canceled fires in two cases:- Merchant void —
POST /v1/payments/{id}/voidwas called to void an authorized/captured payment before settlement. - Customer cancel during 3DS — the customer clicked “Cancel Payment” on the hosted 3DS challenge page. The checkout link becomes immediately reusable; the customer can retry with a different card using the same payment link.
GET /v1/payments/{id} and inspect the transaction’s prior state, or rely on your own state tracking.payment.refunded (Refund Completed)
The
amount_refunded field is only included in payment.refunded events. For partial refunds, it shows the refunded amount.payment.chargeback (Chargeback Occurred)
Signature Verification
Webhook requests include a signature header. Verify this signature using the endpoint’s Webhook Secret to confirm the request was sent by ZAFA PAY.Signature Header
| Environment | Header Name |
|---|---|
| Sandbox | X-Zafapay-Signature-Sandbox |
| Production | X-Zafapay-Signature |
Verification Method
The signature is an HMAC-SHA256 hash of the request body (JSON string), using the endpoint’s Webhook Secret as the key.Node.js
Response
Return HTTP status code2xx when the webhook is successfully received.
Retry
ZAFA PAY automatically retries webhooks in the following cases:- HTTP status code other than
2xxis returned - Connection timeout occurs (10 seconds)
Retry Schedule
| Attempt | Delay After Failure |
|---|---|
| 1st | Immediate |
| 2nd | 1 minute later |
| 3rd | 5 minutes later |
| 4th | 30 minutes later |
| 5th | 2 hours later |
| 6th | 6 hours later |
Best Practices
Ensure Idempotency
The same event may be sent multiple times. Use
transaction_id as a key to prevent duplicate processingReturn Response Quickly
Process webhooks asynchronously and return
200 immediately. Long processing times will cause timeout retries