Webhooks
Subscribe to real-time events from YionStack. When something happens (invoice paid, deal moved, order created), we send an HTTP POST to your registered endpoint.
Event catalogue
Delivery format
Each webhook delivery is an HTTP POST with JSON body and the following headers:
| Header | Description |
|---|---|
| X-YionStack-Signature | HMAC-SHA256 signature of the request body |
| X-YionStack-Timestamp | Unix timestamp (seconds) when the event was sent |
| X-YionStack-Event | Event type (e.g. invoice.paid) |
| Content-Type | application/json |
Signature verification
Always verify the X-YionStack-Signature header to ensure the webhook was sent by YionStack and not tampered with.
const crypto = require('crypto');
function verifyWebhook(body, signature, secret) {
const expected = crypto
.createHash('sha256')
.update(secret + '.' + body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// In your Express handler:
app.post('/webhooks/yionstack', (req, res) => {
const signature = req.headers['x-yionstack-signature'];
const timestamp = req.headers['x-yionstack-timestamp'];
const body = JSON.stringify(req.body);
// Reject if timestamp is more than 5 minutes old (replay protection)
const age = Math.floor(Date.now() / 1000) - Number(timestamp);
if (age > 300) return res.status(400).send('Stale webhook');
if (!verifyWebhook(body, signature, 'your_webhook_secret')) {
return res.status(401).send('Invalid signature');
}
// Process the event
const { event, data } = req.body;
console.log('Received:', event, data);
res.status(200).send('OK');
});Retry policy
If your endpoint returns a non-2xx status code or times out (10 seconds), we retry with exponential backoff:
- Attempt 1: immediate
- Attempt 2: after ~2 seconds
- Attempt 3: after ~4 seconds
After 3 failed attempts, the delivery is marked as failed. You can view delivery history in Settings → Developer.