Per-contact run timeline

Search Documentation

Search across all developer documentation

workflows

Per-contact run timeline

GET /v1/workflows/{id}/runs/{runId}/timeline
Auth required api.workflows.view

The ordered step history of one contact's run. A send_filtered event carries filter_tier/filter_reason explaining why the send was skipped (consent opt-out, global unsubscribe, suppression, or frequency cap). A frequency-cap skip's detail says which cap stopped it and who spent the budget, e.g. frequency cap reached (3 sends in 14d across workflows: New-Signup Onboarding ×2, Passive Interest ×1), frequency cap reached (2 sends in 14d in this workflow) for a workflow declaring frequency cap N per D in this workflow, or org frequency cap reached (…) when such a workflow had room but the org-wide default, which always counts every workflow's sends, did not.

A call webhook step writes webhook_called when it is dispatched and then exactly one of webhook_delivered, webhook_failed or webhook_skipped; webhook_held appears in between when the workflow requires review before sending. Their detail is a JSON object rather than a sentence — see the detail field. A webhook_shadowed event's detail is reduced to {key, label} on this API: the recorded envelope carries the contact's attributes and stays behind the dashboard.

Path parameters

id string required

The workflow's UUID or, when the value does not parse as a UUID, its org-unique key. Unknown handles read as 404 not_found. Accepted on every workflow route, read and write alike.

runId string<uuid> required

The run id.

Responses

Errors follow the RFC 7807 problem format — see the error reference.

200 The run's step timeline application/json
run_id string<uuid> required
events array<object> required

Each entry in events:

node_path string required
repeat_iteration integer optional
split_arm integer optional
event_type string required

The run kinds: enrolled, step_entered, wait_started, wait_met, wait_timed_out, send_filtered, send_held, send_skipped, send_failed, send_deferred, exited, completed, failed. The call webhook kinds: webhook_called (the call was dispatched), webhook_delivered (the endpoint answered 2xx), webhook_failed (it answered no, could not be reached, or the 30-minute deadline passed — the run takes the failed: arm), webhook_held (parked in the approvals queue) and webhook_skipped (a reviewer skipped it; the run continues after the whole statement, NOT into the failed: arm). The shadow kinds, written by a workflow running in shadow mode, which records what it would have done and does none of it: send_shadowed, attr_set_shadowed, list_add_shadowed and webhook_shadowed.

exit_kind string optional
exit_name string optional
detail string optional

Human-readable free-text context on most kinds. On the webhook_* kinds it is a JSON object serialised as a string: webhook_called carries {key, label, delivery_id}; webhook_delivered {key, label, status_code, attempts, response_time_ms}; webhook_failed {key, label, status_code, attempts, failure_reason}, with status_code absent when nothing answered; webhook_held and webhook_skipped {key, label}, the latter plus the reviewer's detail. webhook_shadowed carries {key, label} on this API only. The recorded envelope a shadow run would have POSTed includes the contact's attributes, so it is not projected here; read it in the dashboard.

filter_tier string optional

On a send_filtered event, the gate that dropped the send: frequency_cap, account, or topic.

filter_reason string optional

On a send_filtered event, the specific cause: frequency_cap, suppressed, unsubscribed_all, or opted_out.

delivery_outcome string enum optional

On the step_entered event of a send step whose email went out, what SES did with it afterwards. rendering_failed: SES accepted the send and then could not render the template, so nothing was delivered. bounced includes an SES reject. complained: delivered, then marked as spam. pending: no delivery outcome reported yet. When a message has several events the worst wins, in that order. Absent on every other event.

One of: delivered, bounced, complained, rendering_failed, pending

delivery_reason string optional

With delivery_outcome: SES's rendering error for rendering_failed (for example "Attribute 'frontendUrl' is not present in the rendering data."), or the bounce type and sub-type for bounced.

occurred_at string<date-time> required
401 Missing, malformed, or unknown API key application/problem+json
403 Key lacks the required scope or plan limit violated application/problem+json
404 Resource not found application/problem+json
429 Per-org rate limit exceeded application/problem+json
500 Unexpected server-side failure. The code is internal_error. The request_id field can be quoted to SendOps support to investigate. application/problem+json