unit U1 — 1 of 4
Anatomy of a webhook
headers, signatures, idempotency keys
A webhook is an HTTP POST your flow receives the moment something happens in a client's system — a form submission, a payment, a CRM update. Unlike polling, you never ask “anything new?” on a timer; the source pushes the event to a URL you own. A Webhook trigger mints that URL and hands you the request the instant it lands. The catch: you now run a public endpoint strangers can hit, so every field is untrusted until proven otherwise.
Three parts carry the meaning. The body is the event payload — usually JSON, sometimes form-encoded. The headers carry metadata the body can’t be trusted for: a signature proving the sender knows a shared secret, a content-type, and a delivery id. That delivery id is your idempotency key — the same logical event can arrive twice, and the id is how you recognise the duplicate before you act on it twice.
Where it breaks: treating the body as authoritative. A field like `"verified": true` means nothing — anyone can POST it. Identity comes from the signature header, freshness from a timestamp, de-duplication from the delivery id. Read those first, the business fields second.
worked example
A payment-style webhook arriving at your Webhook trigger — note where identity and idempotency actually live.
POST /webhook/lead-intake HTTP/1.1
Host: hooks.youragency.dev
Content-Type: application/json
Webhook-Id: evt_1P9x2kL9
Webhook-Timestamp: 1736784000
Webhook-Signature: v1,3f9a2c...c21
Idempotency-Key: evt_1P9x2kL9
{
"event": "lead.created",
"data": { "email": "[email protected]", "source": "portal-a" }
}field checklist
- Mint the endpoint from the Webhook trigger; never a guessable path.
- Read the signature header before touching any body field.
- Capture the delivery id as your idempotency key.
- Respond 2xx fast; defer heavy work past the response.
- Log raw headers on every delivery for later disputes.
common failure — Trusting a body field for identity
A flow gated on `payload.verified === true` shipped, and a scripted POST with that field flipped set off the whole pipeline for a fake lead. The body is attacker-controlled; only the signature header proves the sender. Move every identity and authorisation check to the headers, and treat the body purely as data to validate against a schema.
check your understanding
A delivery arrives with `"verified": true` in its JSON body. What actually establishes that this request came from the provider and not from someone with your endpoint URL?
next unit opens once this is passed
sandbox validation
The check above confirms you followed the unit. Marking the module COMPLETED takes more: build the automation in your own engine and submit the exported flow and its run evidence, signed, to your unique validation URL. See the module page for that spec.