Webhooks Overview
Webhooks allow you to receive real-time notifications when order status changes occur in Courimax.
How Webhooks Work
- Configure Webhook URL: Set your endpoint URL when creating an API key
- Events Occur: Order status changes trigger webhook events
- HTTP POST: Courimax sends POST requests to your endpoint
- Process Events: Your application processes the events
Configuring Webhooks
Set your webhook URL when creating an API key:
curl -X POST "https://api.courimax.com/api/provisioning/organizations/org-uuid/api-keys" \
-H "X-Provisioning-Secret: your_secret" \
-H "Content-Type: application/json" \
-d '{
"name": "Production API Key",
"platform": "yango",
"webhookUrl": "https://your-app.com/webhooks/courimax"
}'
Webhook Security
HTTPS Required
All webhook endpoints must use HTTPS. HTTP endpoints will be rejected.
Signature Verification
Each webhook request includes a signature in the X-Courimax-Signature header:
X-Courimax-Signature: sha256=abc123...
Verify the signature to ensure the request is authentic:
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return `sha256=${expectedSignature}` === signature;
}
// In your webhook handler
app.post('/webhooks/courimax', (req, res) => {
const signature = req.headers['x-courimax-signature'];
const payload = JSON.stringify(req.body);
if (!verifyWebhookSignature(payload, signature, WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Process webhook
handleWebhook(req.body);
res.status(200).send('OK');
});
IP Whitelisting
For additional security, whitelist Courimax webhook IPs:
52.86.0.0/16
54.239.0.0/16
Contact support for the complete list of webhook source IPs.
Retry Policy
If your endpoint returns a non-2xx response, Courimax will retry:
- Attempt 1: Immediate
- Attempt 2: After 1 minute
- Attempt 3: After 5 minutes
- Attempt 4: After 30 minutes
- Attempt 5: After 2 hours
After 5 failed attempts, the webhook is marked as failed and can be manually replayed.
Timeout
Webhook requests timeout after 30 seconds. Your endpoint should:
- Respond quickly with 200 OK
- Process events asynchronously
- Handle idempotency (events may be delivered multiple times)
Monitoring Webhook Deliveries
Check webhook delivery status via the admin API:
curl -X GET "https://api.courimax.com/api/admin/integrations/webhook-deliveries?limit=50" \
-H "Authorization: Bearer your_jwt_token"
Response:
[
{
"id": "delivery-uuid",
"event": "order.delivered",
"webhookUrl": "https://your-app.com/webhooks/courimax",
"status": "success",
"responseCode": 200,
"attemptedAt": "2026-08-19T12:00:00.000Z",
"responseTime": 150
}
]
Replaying Failed Webhooks
Manually replay failed webhook deliveries:
curl -X POST "https://api.courimax.com/api/admin/integrations/webhook-deliveries/delivery-uuid/replay" \
-H "Authorization: Bearer your_jwt_token"
Best Practices
Respond Quickly
Return 200 OK immediately and process events asynchronously:
app.post('/webhooks/courimax', async (req, res) => {
// Respond immediately
res.status(200).send('OK');
// Process asynchronously
try {
await processWebhookEvent(req.body);
} catch (error) {
logger.error('Webhook processing failed', error);
}
});
Handle Idempotency
Webhooks may be delivered multiple times. Use the event ID to deduplicate:
const processedEvents = new Set();
app.post('/webhooks/courimax', (req, res) => {
const eventId = req.body.id;
if (processedEvents.has(eventId)) {
return res.status(200).send('Already processed');
}
processedEvents.add(eventId);
handleWebhook(req.body);
res.status(200).send('OK');
});
Verify Signatures
Always verify webhook signatures to prevent spoofing:
if (!verifyWebhookSignature(payload, signature, secret)) {
logger.warn('Invalid webhook signature');
return res.status(401).send('Invalid signature');
}
Log Everything
Log all webhook deliveries for debugging:
app.post('/webhooks/courimax', (req, res) => {
logger.info('Webhook received', {
event: req.body.event,
id: req.body.id,
timestamp: req.body.at
});
handleWebhook(req.body);
res.status(200).send('OK');
});
Monitor Failures
Set up alerts for webhook failures:
app.post('/webhooks/courimax', async (req, res) => {
try {
await processWebhookEvent(req.body);
res.status(200).send('OK');
} catch (error) {
logger.error('Webhook processing failed', error);
// Send alert
sendAlert('Webhook processing failed', error);
res.status(500).send('Processing failed');
}
});
Testing Webhooks
Local Testing
Use ngrok to test webhooks locally:
ngrok http 3000
Set your webhook URL to the ngrok URL:
https://abc123.ngrok.io/webhooks/courimax
Test Events
Trigger test events by creating test orders in sandbox environment.
Webhook Inspector
Use the admin dashboard to inspect webhook deliveries and replay failed events.
Next Steps
- Event Types - Complete list of webhook events
- Payload Format - Webhook payload structure
- API Reference - Complete API documentation