Webhooks
Receive real-time notifications about payment events to keep your systems in sync.
Overview
ZenPay webhooks provide a way for your application to receive real-time notifications when payment events occur. Instead of polling our API for updates, webhooks push notifications to your server whenever events happen, enabling you to automatically respond to payment status changes, refunds, disputes, and more.
Real-time Updates
Get instant notifications about payment events.
Secure Delivery
Enhanced security for your webhook endpoints.
Flexible Integration
Easy integration with any backend system.
Reliable Delivery
Ensures all events reach your application.
Setting Up Webhooks
Follow these steps to configure webhooks for your ZenPay account:
Create a Webhook Endpoint
First, create an endpoint on your server that can receive POST requests from ZenPay:
- The endpoint must be publicly accessible over HTTPS
- It should accept JSON payloads in the request body
- It should return a 2xx status code to acknowledge receipt
Register Your Endpoint
Add your webhook endpoint to your ZenPay account:
- Go to Dashboard → Developers → Webhooks → Add Endpoint
- Enter your endpoint URL
- Select the events you want to receive notifications for
- Generate a webhook secret for signature verification
Verify Webhook Signatures
Implement signature verification in your endpoint code:
- Extract the
Zenpay-Signature
header from incoming requests - Use your webhook secret to verify the signature
- Reject requests with invalid signatures to prevent spoofing
Handle Webhook Events
Process the webhook payload and update your systems accordingly:
- Parse the JSON payload to extract event details
- Check the
event_type
field to determine the appropriate action - Update order status, trigger emails, or perform other business logic
- Implement idempotency to handle potential duplicate events
Event Types
ZenPay webhooks support the following event types:
Event Type | Description | When It's Triggered |
---|---|---|
payment.created | A new payment has been created | When a customer initiates a payment |
payment.pending | Payment is awaiting confirmation | When payment is detected but not yet confirmed |
payment.completed | Payment has been completed successfully | When payment receives required confirmations |
payment.failed | Payment attempt has failed | When payment expires or is rejected |
payment.refunded | Payment has been refunded | When a refund is processed |
checkout.completed | Checkout process completed | When customer completes the checkout flow |
checkout.abandoned | Checkout was started but not completed | When checkout expires without payment |
subscription.created | New subscription has been created | When a customer subscribes to a plan |
subscription.updated | Subscription details have changed | When subscription plan or status changes |
subscription.canceled | Subscription has been canceled | When a subscription is terminated |
Webhook Payload
Each webhook notification contains a JSON payload with information about the event:
{
"id": "evt_5f7e243e8b9c4",
"type": "payment.completed",
"created": 1626285966,
"data": {
"object": {
"id": "pay_6g8h354f9c0d5",
"amount": "99.99",
"currency": "USD",
"crypto_amount": "0.00312",
"crypto_currency": "BTC",
"status": "completed",
"customer": {
"email": "customer@example.com",
"name": "John Doe"
},
"metadata": {
"order_id": "ORD-12345",
"product_id": "PRD-6789"
},
"created": 1626285900,
"updated": 1626285966,
"transaction_hash": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
"confirmation_count": 6,
"checkout_session_id": "cs_7h9i465g0d1e6"
}
}
}
Signature Verification
To ensure webhooks are coming from ZenPay and haven't been tampered with, you should verify the signature:
// Using the ZenPay Node.js SDK
const express = require('express');
const bodyParser = require('body-parser');
const crypto = require('crypto');
const app = express();
// Use raw body parser for webhook signature verification
app.use('/webhooks/zenpay',
bodyParser.raw({ type: 'application/json' }),
(req, res) => {
const payload = req.body;
const signature = req.headers['zenpay-signature'];
const webhookSecret = 'whsec_your_webhook_secret';
// Verify signature
const expectedSignature = crypto
.createHmac('sha256', webhookSecret)
.update(payload)
.digest('hex');
// Check if signatures match
if (signature !== expectedSignature) {
console.error('Invalid signature');
return res.status(400).send('Invalid signature');
}
// Parse the payload
const event = JSON.parse(payload);
// Handle different event types
switch (event.type) {
case 'payment.completed':
// Update order status, send confirmation email, etc.
const paymentId = event.data.object.id;
const amount = event.data.object.amount;
const currency = event.data.object.currency;
console.log(`Payment ${paymentId} completed: ${amount} ${currency}`);
break;
case 'payment.failed':
// Handle failed payment
console.log(`Payment ${event.data.object.id} failed`);
break;
// Handle other event types
default:
console.log(`Unhandled event type: ${event.type}`);
}
// Return a response to acknowledge receipt of the webhook
res.status(200).send('Webhook received');
}
);
app.listen(3000, () => console.log('Webhook server running on port 3000'));
Webhook Testing
Before relying on webhooks in production, test your implementation thoroughly:
Testing Options
- 1
Webhook Tester - Use the webhook tester in your ZenPay dashboard to send test events to your endpoint without creating actual payments.
- 2
Local Development - For local testing, use tools like ngrok or localtunnel to create a public URL that forwards to your local server.
- 3
Test Mode Transactions - Create test payments in your ZenPay test environment to trigger real webhook events.
- 4
Replay Events - Use the webhook logs in your dashboard to replay previous events for testing your handler logic.
Best Practices
Follow these recommendations to ensure reliable webhook processing:
Implementation Recommendations
- 1
Return quickly - Respond to webhooks with a 2xx status code as soon as possible, ideally under 500ms. Process the event asynchronously if needed.
- 2
Implement idempotency - Design your webhook handler to safely process the same event multiple times without causing duplicate operations.
- 3
Monitor webhook deliveries - Regularly check the webhook logs in your dashboard to ensure events are being delivered and processed correctly.
- 4
Use a queue system - For high-volume applications, consider using a message queue to buffer webhook events before processing.
- 5
Set up alerting - Configure alerts for webhook failures or delays to quickly identify and resolve issues.
Troubleshooting
If you're experiencing issues with webhooks, check these common problems:
Common Issues
Webhook Secret Mismatch
Ensure that the webhook secret used for signature verification matches the one in your ZenPay dashboard. If you've regenerated your webhook secret, you'll need to update your code.
Endpoint Not Responding
Check if your server is accessible and responding to webhook requests. ZenPay expects a 2xx response within a certain timeout period, or it will retry the webhook.
Firewall or Security Issues
Make sure your firewall allows incoming connections from ZenPay's IP ranges. Consider whitelisting ZenPay's IP addresses if you're using IP-based filtering.
Incorrect Content Type
ZenPay sends webhooks with Content-Type: application/json
. Ensure your endpoint correctly handles this content type and properly parses the JSON payload.
Next Steps
Now that you've set up webhooks, explore these related features: