Overview
Webhooks allow you to receive real-time notifications when payment events occur. This is essential for updating your application’s state when payments are completed, expired, or fail.
Supported Events
Payment Completed Triggered when a payment is successfully completed and confirmed on the blockchain.
Payment Expired Triggered when a payment expires without being completed.
Setting Up Webhooks
Set your webhook URL in the merchant dashboard or when creating payments:
{
"webhookUrl" : "https://yoursite.com/webhook"
}
Step 2: Create Webhook Endpoint
Create an endpoint in your application to receive webhook notifications:
// Node.js example
const crypto = require ( 'crypto' );
app . post ( '/webhook' , ( req , res ) => {
const signature = req . headers [ 'x-webhook-signature' ];
const payload = JSON . stringify ( req . body );
// Verify webhook signature
const expectedSignature = crypto
. createHmac ( 'sha256' , process . env . WEBHOOK_SECRET )
. update ( payload )
. digest ( 'hex' );
if ( signature !== expectedSignature ) {
return res . status ( 400 ). send ( 'Invalid signature' );
}
// Handle the event
handleWebhookEvent ( req . body );
res . status ( 200 ). send ( 'OK' );
});
Step 3: Handle Events
Process different webhook events in your application:
function handleWebhookEvent ( event ) {
switch ( event . event ) {
case 'payment.completed' :
console . log ( 'Payment completed:' , event . payment . id );
// Update order status, send confirmation email, etc.
break ;
case 'payment.expired' :
console . log ( 'Payment expired:' , event . payment . id );
// Handle expired payment, maybe retry or cancel order
break ;
default :
console . log ( 'Unknown event:' , event . event );
}
}
Webhook Payloads
Payment Completed
{
"event" : "payment.completed" ,
"payment" : {
"id" : "pay_abc123def456" ,
"status" : "completed" ,
"amountCrypto" : "0.00012345" ,
"crypto" : "BTC" ,
"address" : "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa" ,
"incomingTxHash" : "abc123..." ,
"completedAt" : "2024-01-01T00:30:00Z" ,
"customerId" : "cus_V6n6SN2KnsIFCuQU" ,
"orderId" : "order_123" ,
"metadata" : {
"description" : "Premium subscription"
},
"customFields" : {
"customer_name" : "John Doe"
}
},
"timestamp" : "2024-01-01T00:30:00Z"
}
Payment Expired
{
"event" : "payment.expired" ,
"payment" : {
"id" : "pay_abc123def456" ,
"status" : "expired" ,
"expiresAt" : "2024-01-01T01:00:00Z"
},
"timestamp" : "2024-01-01T01:00:00Z"
}
Webhook Verification
All webhooks are signed using HMAC-SHA256 to ensure they come from Transaction API.
Verification Process
Get Webhook Secret
Find your webhook secret in the merchant dashboard.
Create HMAC Hash
Create HMAC-SHA256 hash of the request body using your secret.
Compare Signatures
Compare the computed hash with the X-Webhook-Signature header.
Example Implementation
const crypto = require ( 'crypto' );
function verifyWebhook ( payload , signature , secret ) {
const expectedSignature = crypto
. createHmac ( 'sha256' , secret )
. update ( payload )
. digest ( 'hex' );
return crypto . timingSafeEqual (
Buffer . from ( signature , 'hex' ),
Buffer . from ( expectedSignature , 'hex' )
);
}
// Usage
const isValid = verifyWebhook (
JSON . stringify ( req . body ),
req . headers [ 'x-webhook-signature' ],
process . env . WEBHOOK_SECRET
);
Webhook Retries
Transaction API will retry failed webhook deliveries:
Retry Schedule: 1, 5, 15, 30, 60 minutes
Max Retries: 5 attempts
Timeout: 30 seconds per attempt
Success Response: HTTP 200 status code
Always respond with HTTP 200 to successful webhook processing to prevent retries.
Testing Webhooks
Using ngrok for Local Development
# Install ngrok
npm install -g ngrok
# Expose local server
ngrok http 3000
# Use the HTTPS URL for webhook testing
# Example: https://abc123.ngrok.io/webhook
Webhook Logs
Monitor webhook delivery in your dashboard:
Go to Webhook Logs in your merchant dashboard
View delivery status and response codes
Debug failed deliveries with request/response details
Best Practices
Verify Signatures
Always verify webhook signatures to ensure authenticity.
Handle Duplicates
Implement idempotency to handle duplicate webhook deliveries.
Respond Quickly
Process webhooks asynchronously to avoid timeouts.
Log Everything
Log all webhook events for debugging and auditing.
Common Issues
Check if your endpoint is accessible from the internet
Verify the webhook URL is correct
Ensure your server is running and responding
Signature Verification Failing
Ensure you’re using the correct webhook secret
Check that you’re hashing the raw request body
Verify the signature header format
Implement idempotency using payment IDs
Store processed event IDs to prevent reprocessing