AxioRankDocs

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

EventFires when
tool_call.evaluatedAny outbound tool call is scored (every call).
tool_call.heldA tool call is held for human approval.
card.verifiedAn external MCP/A2A card is preflighted.
inbound.evaluatedAn inbound agent request is verified.
kill_chain.detectedA dangerous multi-step sequence is confirmed.
ml.assessedA model verdict (threat class) is persisted.
approval.pendingA hold is opened and awaits an approver.
approval.resolvedA hold is approved, denied, or expires (auto-deny, resolvedBy: "system").
approval.escalatedA hold is still pending past the workspace's escalation window.
key.createdAn API key is issued.
key.revokedAn API key is revoked.
agent.quarantinedAn agent is quarantined (kill switch).
checkpoint.sealedAn 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.evaluated

v1 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 fresh whsec_… 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 synthetic webhook.test event 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 secret is 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.

On this page