Webhooks
Subscribe your services to AxioRank events with signed, retried, replayable delivery.
Webhooks let your own systems react to AxioRank events in real time (a held tool call, a resolved approval, a detected kill chain) instead of polling. Register an HTTPS endpoint in Dashboard → Webhooks, choose the events you care about, and AxioRank POSTs a signed JSON envelope to you whenever they fire.
Event catalog
| Event | Fires when |
|---|---|
tool_call.evaluated | Any outbound tool call is scored (every call). |
tool_call.held | A tool call is held for human approval. |
card.verified | An external MCP/A2A card is preflighted. |
inbound.evaluated | An inbound agent request is verified. |
kill_chain.detected | A dangerous multi-step sequence is confirmed. |
ml.assessed | A model verdict (threat class) is persisted. |
approval.pending | A hold is opened and awaits an approver. |
approval.resolved | A hold is approved, denied, or expires (auto-deny, resolvedBy: "system"). |
approval.escalated | A hold is still pending past the workspace's escalation window. |
key.created | An API key is issued. |
key.revoked | An API key is revoked. |
agent.quarantined | An agent is quarantined (kill switch). |
checkpoint.sealed | An audit checkpoint is sealed; a new signed tree head is available. |
Subscribe to specific events, or to * for all of them.
Payload
Every delivery is a JSON envelope:
{
"id": "tool_call.evaluated:7f3c…",
"type": "tool_call.evaluated",
"data": {
"workspaceId": "ws_…",
"auditLogId": "7f3c…",
"agentId": "ag_…",
"toolName": "aws.delete_bucket",
"decision": "deny",
"risk": 92,
"signalCategories": ["destructive"]
}
}Delivery is at-least-once and unordered. Dedupe on id and don't assume order. A
replayed delivery carries a replayOf field with the original event id.
Verifying signatures
Every request carries an Axiorank-Signature header:
Axiorank-Signature: t=1717790000,v1=<hex hmac>
Axiorank-Id: tool_call.evaluated:7f3c…
Axiorank-Event: tool_call.evaluatedv1 is HMAC_SHA256(secret, "{t}.{rawBody}"), where secret is the whsec_… shown once when
you created the endpoint. Verify against the exact raw bytes you received (don't re-serialize),
and reject timestamps outside a tolerance window (default 5 minutes) to defeat replay.
The SDKs do this for you:
import { constructEvent } from "@axiorank/sdk";
// In your route handler - pass the RAW body string.
const event = await constructEvent(
rawBody,
req.headers.get("axiorank-signature"),
process.env.AXIORANK_WEBHOOK_SECRET!,
);
// Throws AxioRankWebhookSignatureError on a bad/stale signature.from axiorank import construct_event
event = construct_event(
raw_body, # the exact bytes/str you received
request.headers.get("axiorank-signature"),
os.environ["AXIORANK_WEBHOOK_SECRET"],
)Retries & auto-disable
A non-2xx response (or a timeout) is retried with exponential backoff. After repeated consecutive failures an endpoint is auto-disabled to stop a retry storm against a dead target. Re-enable it from the dashboard once it's healthy. Each attempt is logged under Recent deliveries, where you can Replay any delivery on demand.
Rotating the secret & test events
Both actions live on the endpoint's row in Dashboard → Webhooks (admin role):
- Rotate (
POST /api/webhook-endpoints/{id}/rotate) mints a freshwhsec_…secret, shown exactly once. The old secret stops working immediately, with no grace window, so update the receiver's verification key right away. - Send test (
POST /api/webhook-endpoints/{id}/test) delivers a syntheticwebhook.testevent through the real signing, retry, and delivery-log path, so you can confirm reachability and signature verification end to end. Like a replay, it bypasses the subscription catalog: any enabled endpoint receives it regardless of its event list.
Security notes
- Endpoints must be public HTTPS URLs; private, loopback, and cloud-metadata addresses are refused (at create time and again at delivery).
- The signing
secretis shown once. Store it securely; rotate it from the dashboard when needed (the old secret stops working immediately). - Deliveries are scoped to your workspace; an endpoint only ever receives your own events.