List a blast's sends
GET /
Returns one row per recipient of a blast, the most recently added first.
Scope: blasts:read
Every recipient is listed, sent or not, ordered by when it was added to the blast (then id), newest first, inside the window the first page fixes. The order never uses sent_at, so a row does not move between pages while the blast sends; each row carries its own sent_at.
email finds one recipient. When the member does not see email addresses in full in the blast's campaign it matches nothing: an empty page, never 403. The cursor does not store the address, so send the same email with every cursor of that walk: leaving it out or changing it is 422 invalid_cursor.
Bounced rows carry bounce_code and a short bounce_diagnostic. Email bodies are never returned.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
blast_id | UUID | Yes | The blast. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
status | string | No | Only sends with this status. One of pending, processing, sent, delivered, failed, bounced, suppressed, skipped, cancelled. |
email | string | No | Only the recipient with this address, compared after trimming and lowercasing. |
since | timestamp | No | Only sends whose sent_at is at or after this time, which leaves out recipients not sent yet. ISO 8601; a time without an offset is read as UTC (URL-encode + as %2B). |
limit | integer | No | Sends per page. 1 to 500. Default: 100. |
cursor | string | No | The next_cursor of the previous page, unchanged. The cursor does not store the address, so send the same email with it. Up to 4,096 characters. |
Response
Status: 200 OK
| Name | Type | Description |
|---|---|---|
data | array of objects | Sends, the most recently added first. |
data. | UUID | The send: one recipient of one blast. |
data. | UUID | Its blast. |
data. | UUID | The blast's campaign. |
data. | string | null | The recipient address; null when the member's role hides email, masked (p***@example.net) when it masks it. |
data. | UUID | null | The lead it went to, when the recipient is a lead. |
data. | string | The send status. pending and processing have not gone out yet; suppressed, skipped and cancelled never will. One of pending, processing, sent, delivered, failed, bounced, suppressed, skipped, cancelled. |
data. | timestamp | null | When it went out (RFC 3339, UTC); null while not sent. |
data. | string | null | The mailbox it was sent from, with the same email visibility as email. |
data. | string | null | The subject as the recipient got it; Restricted when the member's role masks messages. |
data. | string | null | Only on bounced sends: the bounce code, for example 5.1.1. |
data. | string | null | Only on bounced sends: the receiving server's message, whitespace collapsed and cut to 200 characters. It quotes the recipient address, so it follows the stricter of email and messages visibility: null when either is hidden, Restricted when either is masked. |
data. | boolean | true when DialEcho matched a reply to this send. |
data. | timestamp | null | When the first matched reply came. |
data. | boolean | true when the recipient opted out in a reply to this send or the provider reported an unsubscribe. |
next_cursor | string | null | Pass it back as cursor for the next page; null when there is none. |
has_more | boolean | true while next_cursor is set. |
Example request
curl
bash
curl "https://development.agencydevworks.ai/v1/blasts/22222222-0000-4000-8000-000000000001/sends?status=bounced&limit=1" \
-H "Authorization: Bearer dei_your_key"JavaScript
js
const response = await fetch("https://development.agencydevworks.ai/v1/blasts/22222222-0000-4000-8000-000000000001/sends?status=bounced&limit=1", {
headers: {
"Authorization": "Bearer dei_your_key",
},
});
const data = await response.json();Example response
Status: 200 OK
json
{
"data": [
{
"id": "11111111-0000-4000-8000-000000000002",
"blast_id": "22222222-0000-4000-8000-000000000001",
"campaign_id": "cccccccc-0000-4000-8000-000000000001",
"email": "gone@example.net",
"lead_id": "aaaaaaaa-0000-4000-8000-000000000002",
"status": "bounced",
"sent_at": "2026-11-03T15:04:10Z",
"from_email": "jordan@outreach.example.com",
"subject": "Sam, your solar quote is ready",
"bounce_code": "5.1.1",
"bounce_diagnostic": "550 5.1.1 <gone@example.net>: Recipient address rejected: User unknown",
"replied": false,
"first_reply_at": null,
"opted_out": false
}
],
"next_cursor": "v2.exampleOpaqueCursor",
"has_more": true
}Errors
| HTTP | Code | When |
|---|---|---|
| 403 | insufficient_scope | The key does not have blasts:read. Checked before the query is validated. |
| 404 | not_found | The blast does not exist or the key cannot read it: another organization, a campaign outside the key, or one where the key's member cannot use email blasts. |
| 409 | resync_required | The cursor expired (after 30 days) or the key's or its member's access changed since it was issued. Start again without a cursor. |
| 422 | invalid_cursor | The cursor was not issued to this key for this blast, was changed, or was sent with different filters or without its email. |
| 422 | invalid_request | blast_id is not a UUID, a filter is invalid (error.fields names the first: status, since, query.limit, query.cursor), or email is not an email address (then error.fields is empty). |
| 503 | dependency_unavailable | Blast data or the access check is temporarily unavailable. Retry with backoff. |
Every endpoint can also answer 401 invalid_api_key, 429 rate_limited and 503 dependency_unavailable. See Errors in the overview.
Related endpoints
- GET
/· Retrieve a blastv1/ blasts/ {blast_id} - GET
/· Look up sendsv1/ sends