Skip to main content

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. Webhook endpoints can be created and managed from the Webhooks tab in the merchant dashboard.

Event Types

Payload

string
Event type (e.g., payment.succeeded)
string
Transaction ID
string
Merchant ID
string
Merchant name
string
Payment status (succeeded, failed, canceled, refunded, chargeback)
string
Payment amount (string format, e.g., "100.00")
string
Currency code
string
Payment method (card, depot, etc.)
string
Saved card ID (pmi_xxx format). Only included for recurring payments or when save_card was used
boolean
true for recurring (subscription) payments
boolean
Only included as true when the card was saved for future use
string
Merchant’s order ID (the value specified when creating the payment)
string
Product name (the value specified when creating the payment)
string
Customer ID (the value specified when creating the payment)
string
Customer’s email address (the value specified when creating the payment)
string
Customer’s phone number (the value specified when creating the payment)
string
Refunded amount (string format. payment.refunded event only)
object
Error details (payment.failed event only)
string
Card brand (visa, mastercard, amex, jcb, etc.)
string
Last 4 digits of the card number
string
Cardholder name
number
Card expiration month
number
Card expiration year
string
Card issuing country (ISO 3166-1 alpha-2 code, e.g., US, JP, SG). Only included when BIN lookup data is available.
string
Card funding type (credit, debit, prepaid). Only included when BIN lookup data is available.
object
Metadata specified when creating the payment
string
Transaction creation timestamp (ISO 8601 format)
string
Webhook sent timestamp (ISO 8601 format)

Payload Examples

payment.succeeded (Payment Successful)

  • payment_method_id is only included when save_card was used or for recurring payments
  • save_card is only included as true when the card was saved in the initial payment
  • is_recurring is true for 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:
  1. Merchant voidPOST /v1/payments/{id}/void was called to void an authorized/captured payment before settlement.
  2. 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.
Both cases send the same event shape. If you need to distinguish them, use 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)

When a chargeback occurs, the transaction amount may be debited from the merchant. Please respond promptly.

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

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 code 2xx when the webhook is successfully received.

Retry

ZAFA PAY automatically retries webhooks in the following cases:
  • HTTP status code other than 2xx is returned
  • Connection timeout occurs (10 seconds)

Retry Schedule

A total of 6 retries are executed over approximately 9 hours. If all retries fail, the event is moved to a Dead Letter Queue (DLQ) for manual intervention.
To prevent duplicate notifications from retries, ensure idempotency using transaction_id as the key.

Best Practices

1

Always Verify Signature

Signature verification is essential to prevent unauthorized requests
2

Ensure Idempotency

The same event may be sent multiple times. Use transaction_id as a key to prevent duplicate processing
3

Return Response Quickly

Process webhooks asynchronously and return 200 immediately. Long processing times will cause timeout retries
4

Log Errors

Log received payloads and processing results for debugging