Skip to content

API: Webhooks

Subscribe to real-time events. Delivered as signed JSON POSTs, retried with exponential backoff for up to 24h.

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).
event.json
{
"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"
}
}
verify-webhook.ts
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));
}