API: Webhooks
Subscribe to real-time events. Delivered as signed JSON POSTs, retried with exponential backoff for up to 24h.
Events
Section titled “Events”| Event | Meaning |
|---|---|
payment.approved |
A payment passed allowance and policy checks. |
payment.blocked |
A payment was refused before money moved. |
budget.exceeded |
An allowance hit its daily or weekly cap. |
service.flagged |
An unknown or newly-seen service was attempted. |
agent.paused |
An agent was paused (manual or auto). |
{ "id": "evt_01JY6K8MYHXNK2WF6BC9G4A3E7", "type": "payment.approved", "createdAt": "2026-06-10T09:31:05Z", "data": { "paymentId": "pay_01JY6K6Y8F7P4B2S1Q8Z9R0M3N", "agentId": "researchbot-01", "service": "risk-report-api", "amount": "0.03", "asset": "USDC", "tx": "5xL...9Qp" }}Verification
Section titled “Verification”import crypto from "node:crypto";
export function verifyAllowKitWebhook(rawBody, headers, secret) { const id = headers["allowkit-webhook-id"]; const ts = headers["allowkit-webhook-timestamp"]; const sig = headers["allowkit-webhook-signature"]; const ageMs = Math.abs(Date.now() - Number(ts) * 1000);
if (!id || !ts || !sig) return false; if (ageMs > 5 * 60 * 1000) return false;
const signed = `${id}.${ts}.${rawBody}`; const expected = crypto .createHmac("sha256", secret) .update(signed) .digest("hex");
return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));}