Documentation Index
Fetch the complete documentation index at: https://agentrail.app/docs/llms.txt
Use this file to discover all available pages before exploring further.
AgentRail signs each webhook delivery with an HMAC signature. Before you process any payload, you must verify that signature against the raw request body and your webhook secret. The parseWebhookEvent function handles verification and deserialization in one call.
Import
import { parseWebhookEvent } from "@agentrail-core/sdk";
Verify and parse a delivery
import { parseWebhookEvent } from "@agentrail-core/sdk";
const event = parseWebhookEvent(rawBody, process.env.AGENTRAIL_WEBHOOK_SECRET!, {
"x-agentrail-subscription-id": req.headers["x-agentrail-subscription-id"],
"x-agentrail-event-id": req.headers["x-agentrail-event-id"],
"x-agentrail-event-type": req.headers["x-agentrail-event-type"],
"x-agentrail-delivery-id": req.headers["x-agentrail-delivery-id"],
"x-agentrail-delivery-attempt": req.headers["x-agentrail-delivery-attempt"],
"x-agentrail-signature": req.headers["x-agentrail-signature"],
});
console.log(event.type, event.data);
parseWebhookEvent throws if the signature does not match or if required headers are missing.
AgentRail sends all of the following headers with every delivery. Pass them exactly as received — do not normalize or rename them.
| Header | Description |
|---|
x-agentrail-subscription-id | ID of the webhook subscription that triggered the delivery |
x-agentrail-event-id | Unique ID for this event |
x-agentrail-event-type | Event type, e.g. task.updated |
x-agentrail-delivery-id | Unique ID for this delivery attempt |
x-agentrail-delivery-attempt | Attempt number (starts at 1) |
x-agentrail-signature | HMAC signature to verify |
Use the raw request body
Pass the raw request body bytes or string to parseWebhookEvent. Do not parse the body as JSON first. JSON re-serialization changes byte ordering and whitespace, which breaks the HMAC signature check.
In Express, read the raw body by configuring express.raw:
import express from "express";
import { parseWebhookEvent } from "@agentrail-core/sdk";
const app = express();
app.post(
"/webhooks/agentrail",
express.raw({ type: "application/json" }),
(req, res) => {
const event = parseWebhookEvent(
req.body,
process.env.AGENTRAIL_WEBHOOK_SECRET!,
{
"x-agentrail-subscription-id": req.headers["x-agentrail-subscription-id"] as string,
"x-agentrail-event-id": req.headers["x-agentrail-event-id"] as string,
"x-agentrail-event-type": req.headers["x-agentrail-event-type"] as string,
"x-agentrail-delivery-id": req.headers["x-agentrail-delivery-id"] as string,
"x-agentrail-delivery-attempt": req.headers["x-agentrail-delivery-attempt"] as string,
"x-agentrail-signature": req.headers["x-agentrail-signature"] as string,
},
);
console.log(event.type, event.data);
res.status(200).send("OK");
},
);
Set the webhook secret
Your webhook secret (AGENTRAIL_WEBHOOK_SECRET) is separate from your API key. You set it when you create a webhook subscription — see POST /event-subscriptions for the secret parameter.