Skip to content
View as Markdown

Look up sends ​

GET /v1/sends

Lists every blast email sent to one address, oldest first.

Scope: blasts:read

Answers "did we email this person, and with what": every send to the address with a sent_at, in any campaign whose blasts the key can read and where its member sees email addresses in full (elsewhere nothing matches, never 403), ordered by sent_at (then id), oldest first, inside the window the first page fixes. Recipients not sent yet, suppressed or skipped were never emailed and are not listed. Rows have the same shape as a blast's sends.

Send the same email with every cursor; the cursor does not store the address.

Query parameters ​

NameTypeRequiredDescription
emailstringYesThe address, compared after trimming and lowercasing.
limitintegerNoSends per page. 1 to 500. Default: 100.
cursorstringNoThe 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

NameTypeDescription
dataarray of objectsSends to the address, oldest first.
data.idUUIDThe send: one recipient of one blast.
data.blast_idUUIDIts blast.
data.campaign_idUUIDThe blast's campaign.
data.emailstring | nullThe recipient address; null when the member's role hides email, masked (p***@example.net) when it masks it.
data.lead_idUUID | nullThe lead it went to, when the recipient is a lead.
data.statusstringThe 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.sent_attimestamp | nullWhen it went out (RFC 3339, UTC); null while not sent.
data.from_emailstring | nullThe mailbox it was sent from, with the same email visibility as email.
data.subjectstring | nullThe subject as the recipient got it; Restricted when the member's role masks messages.
data.bounce_codestring | nullOnly on bounced sends: the bounce code, for example 5.1.1.
data.bounce_diagnosticstring | nullOnly 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.repliedbooleantrue when DialEcho matched a reply to this send.
data.first_reply_attimestamp | nullWhen the first matched reply came.
data.opted_outbooleantrue when the recipient opted out in a reply to this send or the provider reported an unsubscribe.
next_cursorstring | nullPass it back as cursor for the next page; null when there is none.
has_morebooleantrue while next_cursor is set.

Example request ​

curl

bash
curl "https://development.agencydevworks.ai/v1/sends?email=pat@example.com" \
  -H "Authorization: Bearer dei_your_key"

JavaScript

js
const response = await fetch("https://development.agencydevworks.ai/v1/sends?email=pat@example.com", {
  headers: {
    "Authorization": "Bearer dei_your_key",
  },
});
const data = await response.json();

Example response ​

Status: 200 OK

json
{
  "data": [
    {
      "id": "11111111-0000-4000-8000-000000000001",
      "blast_id": "22222222-0000-4000-8000-000000000001",
      "campaign_id": "cccccccc-0000-4000-8000-000000000001",
      "email": "pat@example.com",
      "lead_id": "aaaaaaaa-0000-4000-8000-000000000001",
      "status": "delivered",
      "sent_at": "2026-11-03T15:02:55Z",
      "from_email": "jordan@outreach.example.com",
      "subject": "Pat, your solar quote is ready",
      "bounce_code": null,
      "bounce_diagnostic": null,
      "replied": true,
      "first_reply_at": "2026-11-03T17:41:09Z",
      "opted_out": false
    }
  ],
  "next_cursor": null,
  "has_more": false
}

Errors ​

HTTPCodeWhen
403insufficient_scopeThe key does not have blasts:read. Checked before the query is validated.
409resync_requiredThe cursor expired (after 30 days) or the key's or its member's access changed since it was issued. Start again without a cursor.
422invalid_cursorThe cursor was not issued to this key for this lookup, was changed, or was sent without its email.
422invalid_requestemail is missing (query.email, missing) or is not an email address (then error.fields is empty), or limit or cursor is invalid.
503dependency_unavailableBlast 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.