Overview
Webhooks notify your server when payment events occur. Set the webhookUrl when creating a payment, and Ebioro will POST to that URL whenever the payment status changes.
Webhook Payload
{
"data": {
"type": "transaction_updated",
"id": "pt_ABC123",
"status": "paid",
"settlement_status": "paid",
"amount": {
"value": 1000,
"currency": "USD"
},
"settlement_amount": 1000,
"settlement_currency": "USDC",
"settlement_fee": 25,
"amount_paid": 1000,
"amount_received": 1000,
"amount_remaining": 0,
"history": [
{
"time": 1714124827333,
"status": "success",
"description": "Payment created"
},
{
"time": 1714124900000,
"status": "success",
"description": "Customer paid"
}
],
"metadata": {}
}
}
Event Types
| Type | When |
|---|
transaction_created | Payment order created |
transaction_updated | Payment status changed (paid, underpaid, settled) |
transaction_failed | Payment processing failed |
Verifying Webhooks
Every webhook includes an X-WEBHOOK-AUTH header containing an HMAC-SHA256 signature. Always verify this signature before processing the webhook.
const crypto = require('crypto');
function verifyWebhook(body, signature, secretKey) {
const expected = crypto
.createHmac('sha256', secretKey)
.update(JSON.stringify(body))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
// In your webhook handler:
app.post('/webhook', (req, res) => {
const signature = req.headers['x-webhook-auth'];
if (!verifyWebhook(req.body, signature, YOUR_API_SECRET_KEY)) {
return res.status(401).send('Invalid signature');
}
const { type, status, id } = req.body.data;
// Process the webhook...
res.status(200).send('OK');
});
Requirements
- Webhook URL must use HTTPS in production
- Your endpoint must respond with a 200 status code
- Respond within 10 seconds or the request will time out
Retry Policy
If your endpoint returns a non-200 status code or times out, the webhook is not retried. Make sure your endpoint is reliable.
Always verify the X-WEBHOOK-AUTH signature. Without verification, an attacker could send fake webhook events to your endpoint.