Skip to content

Webhooks Overview

Webhooks notify your server in real time when payment events occur. Instead of polling the API, ZevPay sends an HTTP POST request to your configured webhook URL.

How webhooks work

  1. A payment event occurs (e.g., customer completes a transfer)
  2. ZevPay sends a POST request to the webhook URL configured on your API key
  3. Your server processes the event and responds with a 2xx status code
Customer pays → ZevPay confirms → POST to your webhook URL → You fulfill the order

Setting up webhooks

Configure your webhook URL in the ZevPay Dashboard under Settings → API Keys. Each API key pair (secret + public) shares a webhook URL and webhook secret.

Requirements

  • Your endpoint must be publicly accessible (HTTPS recommended for production)
  • Your endpoint must respond with a 2xx status code within 30 seconds
  • Your endpoint should accept POST requests with Content-Type: application/json

Webhook payload

All webhook payloads follow this structure:

json
{
  "event": "charge.success",
  "data": {
    "reference": "ZVP-CKO-S-abc123",
    "amount": 500000,
    "currency": "NGN",
    "status": "completed",
    // ... event-specific fields
  }
}
FieldTypeDescription
eventstringThe event type (e.g., "charge.success")
dataobjectEvent-specific payload

Security

Every webhook request includes an HMAC-SHA256 signature in the x-zevpay-signature header. Always verify this signature before processing the event.

x-zevpay-signature: a1b2c3d4e5f6...

The signature is computed using your webhook secret (available in the dashboard). See Verifying Signatures for implementation details.

Webhook delivery

PropertyValue
MethodPOST
Content-Typeapplication/json
Timeout30 seconds
Signature headerx-zevpay-signature
Max retries5
DeduplicationPer event + reference

Automatic retries

If your server fails to respond with a 2xx status code (or doesn't respond within 30 seconds), ZevPay will automatically retry the delivery with exponential backoff:

RetryDelay after previous attempt
1st retry~4 minutes
2nd retry~9 minutes
3rd retry~16 minutes
4th retry~25 minutes
5th retry~36 minutes

After 5 failed retries, the webhook is marked as permanently failed. You can manually retry failed webhooks from the dashboard.

WARNING

Make sure your webhook endpoint is reliable and responds quickly. If your server is consistently unresponsive, webhook deliveries will be lost after the retry window expires.

Deduplication

ZevPay prevents duplicate webhook deliveries. If a webhook for the same event and transaction reference has already been successfully delivered to your endpoint, it will not be sent again. This protects against accidental double-processing on our end.

However, you should still implement idempotent handlers on your side — see Handle duplicates below.

Delivery logging

All webhook deliveries are logged with:

  • Delivery status (delivered, failed, or pending)
  • HTTP status code from your server
  • Response time in milliseconds
  • Retry count and last attempt timestamp
  • Request and response body

You can view webhook delivery logs in the dashboard.

Best practices

Respond quickly

Return a 2xx response as fast as possible. Process the event asynchronously if needed:

js
app.post('/webhooks/zevpay', (req, res) => {
  // Respond immediately
  res.status(200).send('OK');

  // Process asynchronously
  processEvent(req.body).catch(console.error);
});

Handle duplicates

Design your webhook handler to be idempotent. Use the reference field to detect and skip duplicate events:

js
async function processEvent(payload) {
  const existing = await db.findByReference(payload.data.reference);
  if (existing) return; // Already processed

  // Process the event
  await fulfillOrder(payload.data);
}

Verify signatures

Always verify the x-zevpay-signature header before processing events. See Verifying Signatures.

Use HTTPS

Always use HTTPS for your webhook endpoint in production to prevent payload interception.

Events reference

EventDescription
charge.successPayment completed successfully

See Events Reference for detailed payload documentation.

ZevPay Checkout Developer Documentation