The two shapes
Which one you receive depends on the kind of sequence the step belongs to, and theevent field
tells you without guessing.
| Sequence | event | Carries |
|---|---|---|
| A journey people are enrolled in | sequence.node.webhook | One contact, as they pass the step |
| A series on a fixed date | sequence.series.webhook | A batch of contacts — the audience of that step |
One contact
json
{
"event": "sequence.node.webhook",
"occurredAt": "2026-09-21T09:00:00.000Z",
"sequence": {"id": "…", "name": "Onboarding"},
"node": {"id": "…"},
"contact": {
"id": "…",
"email": "alice@example.com",
"firstName": "Alice",
"lastName": null
}
}A batch
json
{
"event": "sequence.series.webhook",
"occurredAt": "2026-09-21T09:00:00.000Z",
"sequence": {"id": "…", "name": "Spring launch"},
"node": {"id": "…"},
"batch": {"index": 3, "size": 500},
"contacts": [
{
"id": "…",
"email": "alice@example.com",
"firstName": "Alice",
"lastName": null
}
]
}batch.index is the rank of that batch inside one run of the step, counted from zero, and
batch.size is how many contacts it carries. The pair is stable: if you ever see the same
node.id + batch.index for the same run twice, it is the same contacts — which is what lets you
recognise a batch you already handled.
The audience is frozen when the step starts. Contacts who arrive while the batches are going out
belong to the next step, not to this one.
What is never in it
Three things, and none of them by accident:- no secret — no API key, and no unsubscribe link or token, which is a capability and not an identifier;
- no organization id;
- no response of yours is read — the body you send back is discarded unopened.
What we require of your URL
httpsonly. A plainhttpURL is refused at publication.- A publicly reachable address. Private, local and internal addresses are refused — including a perfectly public host name that resolves to one, and including an address reached through a redirect. Every hop is checked again.
- At most three redirects.
- An answer within five seconds. Past that the call is a timeout. Answer first, work afterwards: acknowledge the request, then do your processing out of band. A batch is sized to fit inside that window, so keep your handler fast rather than thorough.
2xx is a success. Anything else is an error, and nothing about it is guessed at.
When it fails
A failed call is never retried. A webhook call goes out at most once — retrying could create
the same order, the same task or the same record twice on your side. A call that fails is a call
that never happened for you.
| Shown | Meaning |
|---|---|
| succeeded | Your endpoint answered a 2xx. |
| error | Your endpoint answered something else — the status code is shown. |
| timed out | Nothing came back within five seconds. |
| destination refused | Our rules refused the address before anything was sent. |