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 or denied. |
key.created | An API key is issued. |
key.revoked | An API key is revoked. |
agent.quarantined | An agent is quarantined (kill switch). |
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.
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 by recreating the endpoint. - Deliveries are scoped to your workspace; an endpoint only ever receives your own events.