List per-recipient broadcast results

Search Documentation

Search across all developer documentation

broadcasts

List per-recipient broadcast results

GET /v1/broadcasts/{id}/results
Auth required api.broadcasts.view

Returns one page of per-recipient send outcomes for a broadcast, read from the authoritative ClickHouse send log, newest-first. Each row is one recipient decision: sent (handed to SES, message_id set), failed (SES rejected it, failure_reason set), or filtered (dropped by the consent filter before send, filter_tier + failure_reason set). The filtered rows explain the gap between the audience size and the sent count — who was dropped and why. Optionally narrow to one outcome with ?result=. Test-send rows are never included. 404 not_found when the id is not a broadcast in this org.

PII: every row carries the recipient's full email address in email, so paging this endpoint to the end enumerates the broadcast's entire audience. api.broadcasts.view alone is enough — there is no second scope, and nothing is masked. Treat a page of this endpoint as personal data.

Path parameters

id string<uuid> required

Resource UUID. An unparseable id reads as a clean 404 not_found.

Query parameters

result string enum optional

Narrow to one outcome. Omit for all results. unknown and cancelled occur only on broadcasts sent since paced sending.

limit integer optional

Page size (1–200). Default 50.

cursor string optional

Opaque cursor returned from the previous page.

Responses

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

200 Cursor-paginated list of per-recipient outcomes, newest-first application/json
data array<object> required

Each entry in data:

contact_id string required

The contact's id, or empty when the recipient was not a contact.

email string required

The recipient's full email address, in the clear — never masked or truncated, and readable with api.broadcasts.view alone. This field is personal data.

result string enum required

sent: SES accepted the message. failed: SES rejected it for this recipient. filtered: dropped by the consent filter before sending, or because the contact was archived (or its current address was already another recipient of this broadcast) by the time its turn came. unknown: we could not confirm whether SES accepted it, so it may or may not have been delivered; it is never resent automatically. cancelled: still waiting to be sent when the send was cancelled, so it was not sent. Each recipient appears once, with their latest outcome.

One of: sent, failed, filtered, unknown, cancelled

failure_reason string optional

SES rejection reason (failed), drop reason (filtered; contact_archived or duplicate_address when dropped at send time for those), or why the outcome is unknown.

filter_tier string enum optional

Which consent tier dropped the recipient (filtered rows only).

One of: account, topic

message_id string optional

The SES message id (sent rows only).

occurred_at string<date-time> required
pagination object required

Fields of pagination:

has_more boolean required
next_cursor string | null optional
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
422 A query parameter, path value or body field failed validation. The body is a validation_failed Problem. When the refusal is about a reference — a segment key, template slug, topic or attribute name the organization does not have — it additionally carries validation_code, field, line/column, missing, candidates and next_step, so a client can correct the call without a second round of guessing. See ValidationProblem. 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