Register an endpoint
att_wh_<base64url>. Store it
server-side. After a secret rotation, retries and new deliveries are signed
with the new secret; update your receiver promptly, and note that failed
verifications count toward the endpoint’s failure budget.
The delivery
mandate_id, authorization_id when the event belongs to
one, state when it names one, version). Events that name a state carry
it; authorization.committed and its terminal siblings do not. Journal
payload contents never cross. Respond 2xx; anything else is a failure and
the delivery retries.
Verify every delivery
- Parse
tandv1fromAttesso-Signature.tis a canonical base-10 integer in seconds;v1is exactly 64 hex characters. - Check
tis within 300 seconds of your clock (replay window). - Decode the presented secret: strip the
att_wh_prefix, base64url-decode the remainder to its 32 raw bytes, and recompute HMAC-SHA256 over the stringt + "." + bodywith those raw bytes. Compare in constant time againstv1.
Retries and disabling
Failures retry with exponential backoff starting at 30 seconds (plus or minus 20 percent, about nine attempts over roughly 21 hours). After the window the delivery fails terminally and the endpoint’s exhausted-delivery counter grows. An endpoint that fails 20 attempts in a row or exhausts 10 deliveries in a row is disabled automatically; reactivate it (counters reset) once it is healthy again. Deliveries may arrive more than once: deduplicate on the event id. A disabled endpoint’s pending deliveries are frozen and resume on reactivation; a deleted endpoint keeps its history with those deliveries recorded and never retried.Then fetch state
The notification is not the proof. After verifying the signature, fetch the current mandate state and, when you need a durable artifact, the signed evidence bundle (GET /v1/mandates/{mandate_id}/evidence); confirm the
event carries the version you acted on. Delivery stops if the worker is
stopped; state and evidence are the source of truth either way.
