List messages
/v1/email/messagesfor await (const message of bird.email.list({ status: "bounced" })) {
console.log(message.id);
}for message in client.email.list(status="delivered"):
print(message.id)for msg, err := range client.Email.List(context.Background(), bird.EmailListParams{Status: bird.EmailStatusBounced}) {
if err != nil {
log.Fatal(err)
}
fmt.Println(msg.Id)
}foreach ($bird->email->list(['status' => 'delivered']) as $message) {
echo $message->getId(), "\n";
}bird email listcurl -X GET "https://us1.platform.bird.com/v1/email/messages" \
-H "Authorization: Bearer $TOKEN" \
--url-query "limit=25"{
"data": [
{
"id": "em_01krdgeqcxet5s7t44vh8rt9mg",
"from": {
"email": "onboarding@messagebird.dev",
"name": "Bird"
},
"to": [
{
"email": "delivered@messagebird.dev"
}
],
"subject": "Hello from Bird",
"category": "marketing",
"status": "accepted",
"broadcast_id": "eb_01krdgeqcxet5s7t44vh8rt9mg",
"accepted_count": 1,
"processed_count": 0,
"delivered_count": 0,
"bounced_count": 0,
"complained_count": 0,
"deferred_count": 0,
"rejected_count": 0,
"open_count": 0,
"click_count": 0,
"track_opens": false,
"track_clicks": false,
"created_at": "2026-07-01T12:00:00Z"
}
],
"next_cursor": "eyJ2IjoxLCJzIjoiXCIyMDI2LTA1LTI1VDE0OjAzOjEwWlwiIiwiaSI6IjAxOTJmM2IxLTRjN2UtN2EyYi05ZDYxLThmM2E1YzJlN2I0MCJ9",
"prev_cursor": null,
"refresh_cursor": "eyJ2IjoxLCJzIjoiXCIyMDI2LTA1LTI1VDE2OjQyOjAxWlwiIiwiaSI6IjAxOTJmM2IxLTllMDQtN2NkMy1iODE3LTJhNmY0ZDFjOGUwOSJ9"
}
Returns the workspace's sent and scheduled messages, newest first, as a cursor page. Each item has the aggregate delivery status and per-state recipient counts. Message bodies are omitted.
Combine filters to narrow the page:
- Delivery status.
- Category.
- Tag.
- An exact
toorfromaddress. - A
created_afterorcreated_beforetime window.
Query Parameters
limitintegerMaximum number of items to return per page.
starting_afterstringCursor from the next_cursor field of a previous list response. Returns items immediately after the cursor position in the current sort order.
ending_beforestringCursor from the prev_cursor or refresh_cursor field of a previous list response. Returns items immediately before the cursor position in the current sort order. prev_cursor returns the preceding page. refresh_cursor anchors at the first row of that response, which on a newest-first sort is how to fetch the items that have appeared since.
created_afterstringLimits the response to resources created at or after this timestamp. Combine it with created_before to select a time window. Use an RFC 3339 timestamp with a timezone offset.
created_beforestringLimits the response to resources created before this timestamp. Combine it with created_after to select a time window. Use an RFC 3339 timestamp with a timezone offset.
statusstringFilter by aggregate delivery status.
Possible values: scheduled, accepted, processed, deferred, delivered, partial_failure, bounced, complained, rejected, canceled
tagarrayFilter by tag. Accepts name to match any record carrying that tag name, or name:value to match a specific tag pair (for example category:welcome). Repeat the parameter to add more tags. A record must match every tag listed to be returned.
categorystringFilter by category.
Possible values: marketing, transactional
tostringFilter by recipient address. Exact match against any to/cc/bcc recipient on the message. The address is normalized to lowercase before comparison.
fromstringFilter by sender address. Exact match against the message from field. The address is normalized to lowercase before comparison.
Response Payload
dataPage of message objects.
Show child attributes
data.idMessage ID.
data.fromSender address. name is present when a display name was provided on the send.
Show child attributes
data.from.emailEmail address.
data.from.nameDisplay name shown alongside the address in mail clients.
data.toPrimary recipients. Length is the recipient count. Use the broadcasts endpoint for audience-targeted sends. Each entry's name is present when a display name was provided on the send.
Show child attributes
data.to.emailEmail address.
data.to.nameDisplay name shown alongside the address in mail clients.
data.ccCC recipients.
Show child attributes
data.cc.emailEmail address.
data.cc.nameDisplay name shown alongside the address in mail clients.
data.bccBCC recipients.
Show child attributes
data.bcc.emailEmail address.
data.bcc.nameDisplay name shown alongside the address in mail clients.
data.subjectThe subject line as delivered. For a send that used a template, the stored subject is the template's, so this reports it with the send's parameters substituted in, which is what the recipient saw.
data.categoryContent classification, which controls suppression policy:
marketing: Blocks on all suppression reasons.transactional: Allows delivery through complaint and unsubscribe suppressions, for receipts, password resets, and similar operational mail.
Possible values: marketing, transactional
data.reply_toReply-To addresses, if set on the send. Empty/null when no Reply-To was provided.
data.statusdata.accepted_countHow many recipients are in the accepted state, meaning we have the message and are getting ready to deliver it.
data.processed_countHow many recipients the message has been prepared for and queued for delivery.
data.delivered_countHow many recipients' messages were accepted by their mail server.
data.bounced_countNumber of recipients that resulted in a permanent delivery failure.
data.complained_countNumber of recipients that reported spam.
data.deferred_countNumber of recipients in transient delivery deferral. Their mail server asked for a retry, and delivery attempts continue.
data.rejected_countNumber of recipients rejected before delivery. Read the per-recipient rejection_reason field on GET /v1/email/messages/{message_id}/recipients for the specific cause.
data.processing_latency_msTime between the send being accepted and the message being prepared for delivery, in milliseconds, for the fastest recipient. Null until the first recipient reaches processed.
data.delivery_latency_msTime between the message being processed and the receiving mail server accepting it, in milliseconds, for the fastest delivered recipient. Null until the first recipient is delivered.
data.total_latency_msEnd-to-end accept → delivered time for the fastest delivered recipient, in milliseconds. Null until the first recipient is delivered.
data.open_countTotal open events across all recipients.
data.click_countTotal click events across all recipients.
data.requested_languageThe template language this send asked for, in canonical form (pt-BR for a request of pt-br). Null when the send named no language (it took the template's default) or used no template at all. Compare it with resolved_language: when they differ, the language you asked for was not available and the template's on_missing_language policy chose the one shown there instead.
data.resolved_languageThe template language this send was actually delivered in, in canonical form. Null when the send used no template. A non-null value with a null requested_language means the send named no language and took the template's default.
data.template_idThe template this send rendered from, or null for a send that supplied its content inline.
data.template_version_idThe exact template version this send rendered from, or null for an inline send. A template's live version changes every time you submit it, so this is what identifies the wording that was actually delivered, together with resolved_language.
data.broadcast_idThe broadcast that sent this message. Absent for a send that was not part of a broadcast. A broadcast records one message per recipient, and every one of them carries the same value here.
data.tagsLabels on this message, each one a name and a value, that you can filter and search messages by. Use tags for anything you want to find messages by later, and metadata for data you only want handed back to you.
Show child attributes
data.tags.nameTag name. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 32 characters.
data.tags.valueTag value. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 64 characters.
data.metadataAny JSON you kept on the message. We store it and hand it back in webhook payloads, and that is all it does. If you want to search or filter by it, use tags instead.
data.parametersThe substitution values this send supplied, whether inline or from a template, or null if none were supplied. They are the values applied to subject and to the bodies the content endpoint returns, kept so you can see what produced the delivered copy and not only the result.
data.attachmentsAttachment metadata for the send. Empty when no attachments were included. Raw content is not echoed. When content storage is enabled, download an attachment by its id via the message's attachment endpoint.
Show child attributes
data.attachments.idAttachment ID, stable per email send.
data.attachments.filenameFilename as shown to the recipient.
data.attachments.content_typeResolved MIME type at send time.
data.attachments.sizeDecoded size in bytes.
data.attachments.inlineTrue when the attachment was sent inline via a content_id reference in the HTML body, false for regular file attachments.
data.attachments.content_idThe Content-ID set at send time, when the attachment was inline.
data.track_opensWhether open tracking is enabled for this send.
data.track_clicksWhether click tracking is enabled for this send.
data.created_atWhen the send request was accepted.
data.thread_idThread this message belongs to, or null when the message is not part of one.
data.in_reply_to_message_idThe message this one is a reply to, if any.
data.delivered_atWhen all recipients reached a terminal delivered state, or null if not yet fully delivered.
data.scheduled_atWhen this message is scheduled to send, for a send created with a future send time. Absent for an immediate send. Stays set after the scheduled send fires.
next_cursorCursor for the next page. Pass back as starting_after to advance forward. null when no next page exists.
prev_cursorCursor for the previous page. Pass back as ending_before to step backward. null when no previous page exists.
refresh_cursorRefresh anchor, the first row of this response. Pass back as ending_before to fetch what precedes it in the current sort order. On a newest-first sort those are the items that have appeared since; on any other sort they are the items that sort earlier, so refreshing such a list means re-fetching it instead. Non-null whenever data is non-empty; null only on an empty page. Distinct from prev_cursor.
Related resources
Continue with the documentation, guides and examples for this topic.