Skip to main content

Webhook Events Catalog

Every Adjudon webhook delivery carries an event name in the x-adjudon-event header and the same name on the body's event field. This page is the catalog: every event currently dispatched, with its full payload schema and a sample JSON. Subscribe to one event by name, several events by listing them, or all events with the * wildcard. Tested against API version v1.

Every delivery body wraps the event-specific payload in a fixed envelope:

Envelope shape — same for every event
{
"event": "<event-name>",
"timestamp": "2026-05-06T10:14:22.317Z",
"data": { /* event-specific payload, PII-scrubbed */ }
}

The data block is what changes per event. Every payload below is the verbatim shape the dispatcher emits today.

Event summary

EventSubscribableFires when
trace.createdyesA DecisionTrace is created with a non-blocked, non-flagged status (the standard approve path)
trace.blockedwildcard onlyA DecisionTrace ingestion is rejected by the Policy Engine (HTTP 403 ADJ_BLOCKED_BY_POLICY)
trace.hold_for_reviewwildcard onlyA DecisionTrace is held for human review (HTTP 202) and a ReviewItem is created
alert.triggeredyesAn alert rule matches a trace
agent.createdyesRoadmap — subscription enum exists; dispatch path not yet wired
setting.updatedyesRoadmap — subscription enum exists; dispatch path not yet wired

The "Subscribable" column is the honesty column. The four events in the model's events enum (trace.created, alert.triggered, agent.created, setting.updated, plus *) are what a webhook can register for at create time. The two trace.blocked and trace.hold_for_review events are dispatched by the server today but are not in the subscription enum yet, so they reach subscribers only via a wildcard (*) subscription. This is documented honestly so procurement and integration engineers do not discover the asymmetry through silent missing deliveries.

trace.created

Fires after a successful trace ingestion (HTTP 201). Approved decisions only; blocked and held decisions fire their own events.

data shape
{
"traceId": "trace_aBcD1234",
"agentName": "underwriter-v1",
"status": "approved",
"latency": 42,
"timestamp": "2026-05-06T10:14:22.317Z"
}
Sample delivery body
{
"event": "trace.created",
"timestamp": "2026-05-06T10:14:22.317Z",
"data": {
"traceId": "trace_aBcD1234",
"agentName": "underwriter-v1",
"status": "approved",
"latency": 42,
"timestamp": "2026-05-06T10:14:22.317Z"
}
}

latency is the millisecond round-trip recorded by the agent at trace-call time. status is the DecisionTrace.status enum value; approved is the typical value here.

trace.blocked

Fires when the Policy Engine returns block and the request gets a 403 ADJ_BLOCKED_BY_POLICY. Subscribable only via * today.

data shape
{
"traceId": "trace_aBcD1234",
"agentName": "underwriter-v1",
"status": "blocked",
"reason": "Policy 'Block low-confidence loan denials' matched",
"timestamp": "2026-05-06T10:14:22.317Z"
}

reason is the matched policy's stored reason text. Use this event to fan out to incident-response channels — a blocked decision is a moment your operator wants visibility on, not after the fact.

trace.hold_for_review

Fires when the Policy Engine returns flag_for_review, the response is HTTP 202, and a ReviewItem is created. Subscribable only via * today.

data shape
{
"traceId": "trace_aBcD1234",
"reviewId": "65b1f2c4d3e0a1b2c3d4e5f6",
"agentName": "underwriter-v1",
"timestamp": "2026-05-06T10:14:22.317Z"
}

The reviewId is the Mongo _id of the created ReviewItem. Route this event to a Slack channel or PagerDuty rotation to bring the human reviewer into the loop within the SLA your organisation has set for human oversight under EU AI Act Article 14.

alert.triggered

Fires when an alert rule matches a trace. The dispatcher sends one event per matching rule, so a trace that triggers two rules produces two deliveries.

data shape
{
"ruleId": "65b1f2c4d3e0a1b2c3d4e5f6",
"ruleName": "Low-confidence finance decisions",
"traceId": "trace_aBcD1234",
"traceIdMongo": "65b1f2c4d3e0a1b2c3d4e5f7",
"condition": "confidenceScore < 0.7 AND tags includes 'finance'",
"valueTriggeredAt": 0.62
}

condition is the rule's stored condition string; valueTriggeredAt is the value (typically a confidence score or a counter) that crossed the threshold. Both fields are intended for triage UIs that want to render the alert without re-querying the rule.

agent.created and setting.updated (roadmap)

Both events are accepted by the subscription enum but have no dispatch path wired today. A subscriber who creates a webhook listening for these events will not see any deliveries.

We document this honestly so integration engineers do not chase silent failures. When the dispatch paths ship, they will appear in the Changelog and the schema for each event will be added here. No "Coming soon" placeholder — if it is not in this catalog with a payload schema, it does not fire.

Subscribing

Subscribe to one event by name, several by listing them, or every event with the * wildcard:

curl — subscribe to all trace events via wildcard
curl -X POST https://api.adjudon.com/api/v1/webhooks \
-H "Authorization: Bearer $ADJUDON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.example.com/adjudon",
"events": ["*"]
}'

The * subscription receives every event the server dispatches, including the dispatch-only events listed above and any new events that ship before they enter the subscription enum.

Versioning of payload shapes

Adjudon treats payload field-additions as backward-compatible: a consumer that ignores unknown fields continues working when we add a new field to an event's data. Field renames or removals require a 90-day deprecation notice in the Changelog. The wrapper envelope (event, timestamp, data) is stable until a major API version bump.

See also