Integrating
Webhooks
Signing, verification, the retry schedule, replay, and what happens to a dead letter.
An endpoint subscribes to event types and receives the envelope every event on the spine carries: id, type, occurred_at, account_id and data. The types are in the event catalogue.
Verify the signature before you parse the body
Each delivery carries a timestamp and an HMAC over timestamp.body using your endpoint's signing secret. Compare with a constant-time comparison and reject a timestamp outside your tolerance window — without the timestamp check a captured delivery can be replayed at you forever.
Read the raw body. A framework that parses JSON and re-serialises it changes bytes, and a signature over re-serialised JSON verifies at random.
Retries
A delivery that does not answer 2xx is retried on a fixed schedule, in minutes:
1, 5, 15, 60, 180, 360, 720, 1440, 2880, 4320That is 10 attempts in total, spread over several days. Delays exist only between attempts; the last failure exhausts the schedule rather than scheduling another one.
Answer fast, work later
Return 2xx as soon as you have stored the event. Doing the work inline means a slow consumer looks like a failing one, and a failing one gets retried — which makes it slower.
Duplicates are expected
At-least-once delivery means the same id can arrive twice: a retry after your 2xx was lost, or a replay you asked for. Deduplicate on the event id.
Dead letters
After the 10th failure the delivery is dead-lettered rather than dropped. The console shows every attempt with its response code and timing, and a dead letter can be replayed once the endpoint is fixed. An endpoint that fails persistently is disabled and the account is notified, so a URL that stopped existing does not quietly become a hole in your event history.
Local development
Point an endpoint at a tunnel, or run the Node SDK CLI from this repository (the package is private and not on the public registry yet):
agentisend webhooks listen --secret whsec_… --forward-to http://localhost:3000/webhooksThe signature headers are forwarded unchanged, byte for byte, so local verification uses the same secret as production.