Back to API docs
Webhooks · 19 events
Webhook reference
Subscribe to events from your workspace — Byro POSTs a signed JSON payload to your endpoint whenever the event fires. Configure endpoints in /admin/webhooks.
Delivery
HTTP POST ·
application/json · 10-second timeout. Idempotent — same event ID won't fire twice.Retries
Failed deliveries (non-2xx response or timeout) retry with exponential backoff: 30s, 2m, 10m, 1h, 6h, 24h. After 6 failures the endpoint is auto-paused.
Signing
Every request includes
X-Byro-Signature — an HMAC-SHA256 of the raw body using your endpoint secret. Verify it before processing.Event catalog
pr (6)
pr.submittedPR submitted{
"event": "pr.submitted",
"data": {
"prId": "clx123",
"amount": 4500,
"currency": "AED",
"submittedBy": "ahmed@acme.com"
},
"deliveredAt": "2026-05-22T09:30:00Z"
}pr.approvedPR approved{
"event": "pr.approved",
"data": {
"prId": "clx123",
"amount": 4500,
"currency": "AED",
"approvedBy": "sara@acme.com"
},
"deliveredAt": "2026-05-22T09:30:00Z"
}pr.rejectedPR rejectedpr.receivedPR receivedpr.closedPR closedpr.cancelledPR cancelledpo (1)
po.issuedPO issued{
"event": "po.issued",
"data": {
"poId": "clx456",
"prId": "clx123",
"supplier": "Apple FZE",
"amount": 4500
},
"deliveredAt": "2026-05-22T09:30:00Z"
}asset (3)
asset.assignedAsset assigned{
"event": "asset.assigned",
"data": {
"assetId": "ast789",
"tag": "BYR-LAP-001",
"employeeId": "emp123",
"assignedAt": "2026-05-22T09:30:00Z"
},
"deliveredAt": "2026-05-22T09:30:00Z"
}asset.unassignedAsset unassignedasset.createdAsset created{
"event": "asset.created",
"data": {
"assetId": "ast789",
"tag": "BYR-LAP-001",
"category": "Laptop",
"purchaseCost": 4500
},
"deliveredAt": "2026-05-22T09:30:00Z"
}employee (2)
employee.createdEmployee created{
"event": "employee.created",
"data": {
"employeeId": "emp123",
"code": "ACM-001",
"name": "Ahmed Khan",
"department": "Engineering"
},
"deliveredAt": "2026-05-22T09:30:00Z"
}employee.offboardedEmployee offboardedinventory (1)
inventory.low_stockInventory low stock{
"event": "inventory.low_stock",
"data": {
"itemId": "inv321",
"sku": "USB-C-1M",
"qty": 3,
"minQty": 10
},
"deliveredAt": "2026-05-22T09:30:00Z"
}expense (3)
expense.submittedExpense submittedexpense.approvedExpense approved{
"event": "expense.approved",
"data": {
"claimId": "exp654",
"amount": 230,
"currency": "AED",
"category": "TRAVEL"
},
"deliveredAt": "2026-05-22T09:30:00Z"
}expense.rejectedExpense rejectedleave (3)
leave.submittedLeave submittedleave.approvedLeave approved{
"event": "leave.approved",
"data": {
"requestId": "lvr987",
"employeeId": "emp123",
"days": 5,
"startDate": "2026-06-01"
},
"deliveredAt": "2026-05-22T09:30:00Z"
}leave.rejectedLeave rejectedVerifying signatures
Always verify the X-Byro-Signature header before processing a webhook. Use constant-time comparison to prevent timing attacks.
// Verify the X-Byro-Signature header (Node.js)
import crypto from "node:crypto";
function verify(body, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(body)
.digest("hex");
// Constant-time compare — never use === for HMAC.
return crypto.timingSafeEqual(
Buffer.from(signature, "hex"),
Buffer.from(expected, "hex"),
);
}
// In your Express handler:
app.post("/webhook", (req, res) => {
const sig = req.header("X-Byro-Signature");
const ok = verify(req.rawBody, sig, process.env.BYRO_WEBHOOK_SECRET);
if (!ok) return res.status(401).send("invalid signature");
// ... process req.body
res.status(200).send("ok");
});Ready to subscribe? Configure your first endpoint in the admin panel.
Go to /admin/webhooks