Emails
List the emails sent from a domain and retrieve a single email together with its activity events using MailerSend's Emails API endpoint.
An email is the record of a message delivered to one recipient. Use these requests to list the emails sent from a domain, filter them by status, interaction, recipient, subject, tag or template, and retrieve a single email together with its activity events.
Emails, activities and messages
- Emails return one row per email, with its current status and a summary of recipient interaction. Use them to build a searchable sending log.
- Activities return one row per event, so a single email appears several times — once as
sent, once asdelivered, once asopened, and so on. Use them to consume an event stream. - Messages return one row per API request. A single message can create many emails.
Get a list of emails
Retrieve the emails sent from one of your domains with this GET request:
GET https://api.mailersend.com/v1/emailsdomain_id, date_from and date_to are required. They keep every query bounded to a single domain and a single time window, which is what allows the endpoint to stay fast over large sending volumes.
Emails are returned newest first.
This endpoint uses page-based pagination: request an arbitrary page with ?page=N, and read meta.current_page from the response. limit accepts up to 1000 rows per page and page is capped at 100, so a date window can be walked in at most 100 requests. To retrieve a longer history, split it into several date_from/date_to windows rather than paging deeper.
Required token scopes and rate limit
Requires a token with one of the activity_read or activity_full scopes.
Requests are limited to 10 requests/minute, shared with GET /v1/activity. Requests to either endpoint are counted against the same per-account budget.
Request parameters
| Query parameter | Type | Required | Limitations | Details |
|---|---|---|---|---|
domain_id | string | yes | Must be a domain that belongs to your account. | An unknown or unparseable ID returns 404. |
date_from | int|string | yes | Timestamp is assumed to be UTC. Must be lower than date_to. The allowed timeframe depends on your plan's data retention limit (1–30 days). | Unix timestamp: 1443651141 or datetime: 2015-10-01 00:00:00 |
date_to | int|string | yes | Timestamp is assumed to be UTC. Must be higher than date_from and must not be in the future. | Unix timestamp: 1443661141 or datetime: 2015-10-01 23:59:59 |
page | int | no | Min: 1, Max: 100 | To reach emails beyond page 100, narrow date_from and date_to |
limit | int | no | Min: 10, Max: 1000 | Default: 25 |
status[] | string[] | no | Possible values: queued, sent, rejected, delivered | Array only. Multiple values are combined with OR. |
interaction[] | string[] | no | Possible values: opened, clicked, unsubscribed, complained, no_interaction | Array only. Multiple values are combined with OR. |
recipient_email | string | no | Must be a valid email address. | Exact match, case-insensitive. |
message_id | string | no | Alphanumeric. | Exact match. |
template_id | string | no | Exact match. | |
subject | string | no | Min: 3 characters | Partial, case-insensitive match. |
tag | string | no | Exact match against a value in the email's tags array. |
Filtering
status[] and interaction[] must be sent as arrays. ?status=sent returns a 422 validation error; the correct form is ?status[]=sent.
Values inside status[] are combined with OR, values inside interaction[] are combined with OR, and the two filters are combined with AND. For example, ?status[]=sent&status[]=delivered&interaction[]=opened returns emails that are sent or delivered and that were opened.
no_interaction matches emails with none of opened, clicked, unsubscribed or complained recorded. It is a filter value only and is never returned in the response.
An example request that returns the delivered emails to one recipient over a two-day window:
GET https://api.mailersend.com/v1/emails?domain_id=7nxe3yGpqQmv&date_from=1443651141&date_to=1443824141&status[]=delivered&recipient_email=tyra.cummerata@example.org&limit=50use MailerSend\MailerSend;
use MailerSend\Helpers\Builder\EmailsParams;
$mailersend = new MailerSend(['api_key' => 'key']);
$emailsParams = (new EmailsParams())
->setDomainId('domain_id')
->setDateFrom(1623073576)
->setDateTo(1623074976)
->setPage(1)
->setLimit(50)
->setStatus(['sent', 'delivered'])
->setInteraction(['opened']);
$mailersend->emails->getAll($emailsParams);import 'dotenv/config';
import { MailerSend, EmailStatus, EmailInteraction } from "mailersend";
const mailerSend = new MailerSend({
apiKey: process.env.API_KEY,
});
const queryParams = {
domain_id: "domain_id",
date_from: 1443651141, // Unix timestamp
date_to: 1443661141, // Unix timestamp
page: 1, // Min: 1, Max: 100
limit: 50, // Min: 10, Max: 1000, Default: 25
status: [EmailStatus.SENT, EmailStatus.DELIVERED],
interaction: [EmailInteraction.OPENED]
}
mailerSend.email.list(queryParams)
.then((response) => console.log(response.body))
.catch((error) => console.log(error.body));from mailersend import MailerSendClient, EmailsBuilder
from datetime import datetime, timedelta
ms = MailerSendClient()
date_from = int((datetime.now() - timedelta(days=7)).timestamp())
date_to = int(datetime.now().timestamp())
request = (EmailsBuilder()
.domain_id("domain-id")
.date_from(date_from)
.date_to(date_to)
.page(1)
.limit(50)
.status(["sent", "delivered"])
.interaction(["opened"])
.build_list_request())
response = ms.emails.list(request)package main
import (
"context"
"log"
"time"
"github.com/mailersend/mailersend-go"
)
var APIKey = "Api Key Here"
func main() {
// Create an instance of the mailersend client
ms := mailersend.NewMailersend(APIKey)
ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
from := time.Now().Add(-24 * time.Hour).Unix()
to := time.Now().Unix()
options := &mailersend.ListEmailOptions{
DomainID: "domain-id",
DateFrom: from,
DateTo: to,
Page: 1,
Limit: 50,
Status: []string{"sent", "delivered"},
Interaction: []string{"opened"},
}
_, _, err := ms.Email.List(ctx, options)
if err != nil {
log.Fatal(err)
}
}import com.mailersend.sdk.MailerSend;
import com.mailersend.sdk.exceptions.MailerSendException;
import com.mailersend.sdk.emails.EmailsList;
import com.mailersend.sdk.emails.EmailListItem;
public void EmailsList() {
MailerSend ms = new MailerSend();
ms.setToken("token");
try {
EmailsList list = ms.emails()
.domainId("domain id")
.dateFrom(1623073576)
.dateTo(1623074976)
.page(1)
.limit(50)
.getEmails();
for (EmailListItem email : list.emails) {
System.out.println(email.id);
System.out.println(email.status);
System.out.println(email.subject);
}
} catch (MailerSendException e) {
e.printStackTrace();
}
}require "mailersend-ruby"
ms_emails = Mailersend::Emails.new
ms_emails.list(domain_id: "xxx2241ll", date_from: 1620643567, date_to: 1623321967, page: 1, limit: 50, status: %w[sent delivered], interaction: %w[opened])Responses
Valid
| Response key | Type | Details |
|---|---|---|
data[].id | string | ID of the email. Pass it to GET /v1/email/{email_id} to fetch the full email and its activity. |
data[].from | string | The sender's email address. |
data[].to | string | The recipient's email address. |
data[].subject | string | |
data[].text | null | Present but always null in the list. Use GET /v1/email/{email_id} to read message content. |
data[].html | null | Present but always null in the list. Use GET /v1/email/{email_id} to read message content. |
data[].template_id | string|null | null when no template was used. |
data[].domain_id | string | |
data[].message_id | string | ID of the message that created this email. |
data[].status | string | One of queued, sent, rejected, delivered. |
data[].tags | string[]|null | null when the email was sent without tags. |
data[].interaction | string[] | Any of opened, clicked, unsubscribed, complained recorded for the email. An empty array when there was no interaction. |
data[].suppression_reason | string|null | Only set when status is rejected. One of on_hold, hard_bounced, unsubscribed, spam_complained, blocklisted. Otherwise null. |
data[].created_at | datetime | |
data[].updated_at | datetime | |
data[].headers | object|null | Custom headers the email was sent with. null when it was sent without any. |
links.first | string | Full URL of the first page, with all your query parameters preserved. |
links.last | null | Always null. |
links.prev | string|null | Full URL of the previous page. null on the first page. |
links.next | string|null | Full URL of the next page. null on the last page. |
meta.current_page | int | The effective page. |
meta.current_page_url | string | Full URL of the current page. |
meta.from | int | Index of the first row on this page within the result set. |
meta.path | string | |
meta.per_page | int | The effective limit. |
meta.to | int | Index of the last row on this page within the result set. |
Response Code: 200 OK
Response Headers:
content-type: application/json{
"data": [
{
"id": "5ee0b166b251345e407c9201",
"from": "colleen.wiza@example.net",
"to": "tyra.cummerata@example.org",
"subject": "Magni aperiam sunt nam omnis.",
"text": null,
"html": null,
"template_id": "3z0vklorxjy7qrne",
"domain_id": "7nxe3yGpqQmv",
"message_id": "5ee0b182b251345e407c935a",
"status": "delivered",
"tags": ["receipt", "order"],
"interaction": ["opened", "clicked"],
"suppression_reason": null,
"created_at": "2020-06-04T12:00:00.000000Z",
"updated_at": "2020-06-04T12:01:13.000000Z",
"headers": null
},
{
"id": "5ee0b166b251345e407c9202",
"from": "colleen.wiza@example.net",
"to": "blocked.recipient@example.org",
"subject": "Magni aperiam sunt nam omnis.",
"text": null,
"html": null,
"template_id": null,
"domain_id": "7nxe3yGpqQmv",
"message_id": "5ee0b182b251345e407c935a",
"status": "rejected",
"tags": null,
"interaction": [],
"suppression_reason": "hard_bounced",
"created_at": "2020-06-04T11:58:41.000000Z",
"updated_at": "2020-06-04T11:58:41.000000Z",
"headers": null
},
{
"id": "5ee0b166b251345e407c9203",
"from": "colleen.wiza@example.net",
"to": "colleen.wiza@example.net",
"subject": "Voluptatem accusantium doloremque.",
"text": null,
"html": null,
"template_id": null,
"domain_id": "7nxe3yGpqQmv",
"message_id": "5ee0b182b251345e407c935c",
"status": "queued",
"tags": null,
"interaction": [],
"suppression_reason": null,
"created_at": "2020-06-04T11:55:02.000000Z",
"updated_at": "2020-06-04T11:55:02.000000Z",
"headers": {
"X-Order-Id": "8f2c14"
}
}
],
"links": {
"first": "https:\/\/api.mailersend.com\/v1\/emails?domain_id=7nxe3yGpqQmv&date_from=1443651141&date_to=1443824141&limit=10&page=1",
"last": null,
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"current_page_url": "https:\/\/api.mailersend.com\/v1\/emails?domain_id=7nxe3yGpqQmv&date_from=1443651141&date_to=1443824141&limit=10&page=1",
"from": 1,
"path": "https:\/\/api.mailersend.com\/v1\/emails",
"per_page": 10,
"to": 3
}
}Message content in the list
text and html are present in every row but are always null — the list does not read message content. Use GET /v1/email/{email_id} to retrieve the body of a specific email.
The list also does not include recipient or activity. Both are returned by GET /v1/email/{email_id}.
Paginating through the results
Request a page with ?page=N, or follow the URL in links.next verbatim — it already carries domain_id, date_from, date_to, limit and every filter you sent, so nothing needs to be re-added. Keep requesting the next page until links.next is null.
The response deliberately carries no total and no last_page, and links.last is always null — counting every matching row would mean a COUNT over a very large table. You therefore cannot size the result set or jump straight to the end: the only way to know whether more results exist is to check links.next.
If you build page URLs yourself, send page alongside the same domain_id, date_from, date_to and filters as the original request — dropping any of the required parameters returns a 422.
Empty result
A filter that matches nothing — including an unknown recipient_email — returns 200 OK with an empty data array, not a 404.
{
"data": [],
"links": {
"first": "https:\/\/api.mailersend.com\/v1\/emails?domain_id=7nxe3yGpqQmv&date_from=1443651141&date_to=1443824141&limit=25&page=1",
"last": null,
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"current_page_url": "https:\/\/api.mailersend.com\/v1\/emails?domain_id=7nxe3yGpqQmv&date_from=1443651141&date_to=1443824141&limit=25&page=1",
"from": null,
"path": "https:\/\/api.mailersend.com\/v1\/emails",
"per_page": 25,
"to": null
}
}Errors
Response Code: 404 Not FoundReturned when domain_id is missing from your account, unknown or unparseable.
Response Code: 422 Unprocessable EntityReturned when a required parameter is missing or a parameter is invalid — including date_to in the future, a date_from outside your plan's data retention window, status or interaction sent as a scalar instead of an array, a subject shorter than 3 characters, a limit above 1000, or a page above 100. The error body has the same shape as GET /v1/activity.
See - Validation errors
Get a single email
Retrieve a single email, its content and its activity events with this GET request:
GET https://api.mailersend.com/v1/email/{email_id}Required token scopes
Requires a token with one of the email_full, activity_read or activity_full scopes.
Request parameters
| URL parameter | Type | Required | Limitations | Details |
|---|---|---|---|---|
email_id | string | yes | The id of an email, as returned by GET /v1/emails. |
use MailerSend\MailerSend;
$mailersend = new MailerSend(['api_key' => 'key']);
$mailersend->emails->find('email_id');import 'dotenv/config';
import { MailerSend } from "mailersend";
const mailerSend = new MailerSend({
apiKey: process.env.API_KEY,
});
mailerSend.email.single("email_id")
.then((response) => console.log(response.body))
.catch((error) => console.log(error.body));from mailersend import MailerSendClient, EmailsBuilder
ms = MailerSendClient()
request = (EmailsBuilder()
.email_id("email-id")
.build_get_request())
response = ms.emails.get(request)package main
import (
"context"
"log"
"time"
"github.com/mailersend/mailersend-go"
)
var APIKey = "Api Key Here"
func main() {
// Create an instance of the mailersend client
ms := mailersend.NewMailersend(APIKey)
ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
emailID := "email-id"
_, _, err := ms.Email.Get(ctx, emailID)
if err != nil {
log.Fatal(err)
}
}import com.mailersend.sdk.MailerSend;
import com.mailersend.sdk.exceptions.MailerSendException;
import com.mailersend.sdk.emails.EmailInfo;
import com.mailersend.sdk.emails.EmailActivity;
public void SingleEmail() {
MailerSend ms = new MailerSend();
ms.setToken("token");
try {
EmailInfo email = ms.emails().getEmail("email id");
System.out.println(email.id);
System.out.println(email.status);
System.out.println(email.subject);
for (EmailActivity activity : email.activity) {
System.out.println(activity.type);
System.out.println(activity.createdAt.toString());
}
} catch (MailerSendException e) {
e.printStackTrace();
}
}require "mailersend-ruby"
ms_emails = Mailersend::Emails.new
ms_emails.single(email_id: "5ee0b166b251345e407c9201")Responses
Valid
| Response key | Type | Details |
|---|---|---|
data.id | string | |
data.from | string | The sender's email address. |
data.to | string | The recipient's email address. |
data.subject | string | |
data.text | string|null | null when content tracking is disabled for the domain. |
data.html | string|null | null when content tracking is disabled for the domain. |
data.template_id | string|null | null when no template was used. |
data.domain_id | string | |
data.message_id | string | ID of the message that created this email. |
data.status | string | One of queued, sent, rejected, delivered. |
data.tags | string[]|null | null when the email was sent without tags. |
data.interaction | string[] | Any of opened, clicked, unsubscribed, complained recorded for the email. An empty array when there was no interaction. |
data.suppression_reason | string|null | Only set when status is rejected. One of on_hold, hard_bounced, unsubscribed, spam_complained, blocklisted. Otherwise null. |
data.created_at | datetime | |
data.updated_at | datetime | |
data.headers | object|null | Custom headers the email was sent with. null when it was sent without any. |
data.recipient.* | object | The recipient the email was addressed to. Not returned by GET /v1/emails. |
data.activity[] | object[] | Activity events recorded for this email, newest first. An empty array when no events were recorded. |
data.activity[].id | string | ID of the event. Pass it to GET /v1/activities/{activity_id} for the full event. |
data.activity[].type | string | The event type. See Activity status list. |
data.activity[].created_at | datetime | |
data.activity[].suppression_reason | string | Only present on suppressed events. One of on_hold, hard_bounced, unsubscribed, spam_complained, blocklisted. |
About the activity array
- Events are returned newest first and are capped at 200 events per email. Emails with more than 200 events return only the 200 most recent ones. There is no pagination on this array — use
GET/v1/activity if you need the complete event history for a domain. - The
junkevent type is reported assoft_bounced, matching how junk placement is surfaced elsewhere in MailerSend. deferredandsuppressedevents are only included if your plan has those features enabled. They are available on the Starter plan and above.activityis returned even when content tracking is disabled for the domain. In that casehtmlandtextarenullbut the events are still present — event metadata is not message content.
Response Code: 200 OK
Response Headers:
content-type: application/json{
"data": {
"id": "5ee0b166b251345e407c9201",
"from": "colleen.wiza@example.net",
"to": "tyra.cummerata@example.org",
"subject": "Magni aperiam sunt nam omnis.",
"text": "Lorem ipsum dolor sit amet, consectetuer adipiscin",
"html": "<html><body><a href='https://www.mailersend.com' t",
"template_id": "3z0vklorxjy7qrne",
"domain_id": "7nxe3yGpqQmv",
"message_id": "5ee0b182b251345e407c935a",
"status": "delivered",
"tags": ["receipt", "order"],
"interaction": ["opened", "clicked"],
"suppression_reason": null,
"created_at": "2020-06-04T12:00:00.000000Z",
"updated_at": "2020-06-04T12:01:13.000000Z",
"headers": null,
"recipient": {
"id": "5ee0b166b251345e407c9200",
"email": "tyra.cummerata@example.org",
"created_at": "2020-06-04T12:00:00.000000Z",
"updated_at": "2020-06-04T12:00:00.000000Z",
"deleted_at": ""
},
"activity": [
{
"id": "5ee0b166b251345e407c9210",
"type": "clicked",
"created_at": "2020-06-04T12:01:13.000000Z"
},
{
"id": "5ee0b166b251345e407c9209",
"type": "opened",
"created_at": "2020-06-04T12:00:58.000000Z"
},
{
"id": "5ee0b166b251345e407c9208",
"type": "delivered",
"created_at": "2020-06-04T12:00:11.000000Z"
},
{
"id": "5ee0b166b251345e407c9207",
"type": "sent",
"created_at": "2020-06-04T12:00:02.000000Z"
},
{
"id": "5ee0b166b251345e407c9206",
"type": "queued",
"created_at": "2020-06-04T12:00:00.000000Z"
}
]
}
}Valid, with content tracking disabled
When content tracking is turned off in the domain settings, html and text are null. Every other field, including the activity array, is unaffected.
{
"data": {
"id": "5ee0b166b251345e407c9202",
"from": "colleen.wiza@example.net",
"to": "blocked.recipient@example.org",
"subject": "Magni aperiam sunt nam omnis.",
"text": null,
"html": null,
"template_id": null,
"domain_id": "7nxe3yGpqQmv",
"message_id": "5ee0b182b251345e407c935a",
"status": "rejected",
"tags": null,
"interaction": [],
"suppression_reason": "hard_bounced",
"created_at": "2020-06-04T11:58:41.000000Z",
"updated_at": "2020-06-04T11:58:41.000000Z",
"headers": null,
"recipient": {
"id": "5ee0b166b251345e407c9204",
"email": "blocked.recipient@example.org",
"created_at": "2020-06-04T11:58:41.000000Z",
"updated_at": "2020-06-04T11:58:41.000000Z",
"deleted_at": ""
},
"activity": [
{
"id": "5ee0b166b251345e407c9212",
"type": "suppressed",
"created_at": "2020-06-04T11:58:41.000000Z",
"suppression_reason": "hard_bounced"
},
{
"id": "5ee0b166b251345e407c9211",
"type": "queued",
"created_at": "2020-06-04T11:58:41.000000Z"
}
]
}
}Error
Response Code: 404 Not FoundReturned when the email does not exist or belongs to another account.
Activity
Retrieve a list of activities to easily view information about your domain activity including sent emails and their statuses. Learn more with our API documentation.
Analytics
Track the performance of your transactional emails with MailerSend's Analytics API endpoint. Discover opens by country, email activity and more.