API reference
Emails
Send email from your verified domains, one at a time or up to 100 per call, now or at a later time, and follow what happens to every message.
Every endpoint can also return the common errors listed in the overview
(authentication, the per-second rate limit and application_error). For a guided introduction see
Sending email.
| Endpoint | Node.js | Python | CLI |
|---|---|---|---|
| POST /emails | emails.send | emails.send | tsmart emails send |
| POST /emails/batch | batch.send | batch.send | tsmart batch send |
| GET /emails | emails.list | emails.list | tsmart emails list |
| GET /emails/{id} | emails.get | emails.get | tsmart emails get |
| PATCH /emails/{id} | emails.update | emails.update | tsmart emails reschedule |
| POST /emails/{id}/cancel | emails.cancel | emails.cancel | tsmart emails cancel |
| GET /emails/{id}/events | emails.events | emails.events | tsmart emails events |
| GET /emails/metrics | emails.metrics | emails.metrics | tsmart metrics |
POST /emails
Sends one email now, or schedules it with scheduled_at.
Permission: any key. A key restricted to one domain can only send from that domain.
Headers
| Name | Type | Description |
|---|---|---|
Idempotency-Key | string | Optional, 1 to 256 characters. A retry with the same key and body within 24 hours returns the first response and sends nothing again. See Idempotency in the overview. |
Body
| Name | Type | Description |
|---|---|---|
from required | string | Sender, with or without a display name: "Acme <hello@yourdomain.com>" or "hello@yourdomain.com". Exactly one address, at most 320 characters. Its domain must be one of your company's domains with status verified: ownership proven and SPF and DKIM found at the last check. |
to required | string | string[] | One address or an array of addresses, each with or without a display name. At least one, at most 50. |
subject required | string | A single line, at most 998 characters. |
html | string | HTML body, at most 2,000,000 characters. html or text is required. |
text | string | Plain-text body, at most 2,000,000 characters. When omitted, a text part is generated from html; an empty string sends no text part. |
cc | string | string[] | Carbon-copy recipients. |
bcc | string | string[] | Blind carbon-copy recipients. |
reply_to | string | string[] | Reply-To addresses (replyTo is also accepted). |
headers | object | Extra headers as name: value, at most 30. Allowed names: X-… custom headers (up to 60 letters, digits or dashes after X-), List-Unsubscribe, List-Unsubscribe-Post, In-Reply-To and References. Values are single-line strings of at most 998 characters. |
attachments | object[] | Files sent with the email, at most 20. At most 20 MB in total after decoding; base64 makes files about a third larger, and the whole request body may be at most 30 MB. See the attachment fields below. |
tags | object[] | At most 20 { name, value } pairs. Both are 1 to 256 ASCII letters, digits, underscores or dashes. Tags come back in GET /emails/{id} and in webhook payloads. |
scheduled_at | string | Send later: ISO 8601 with a time zone ("2026-10-13T09:00:00+03:00", "2026-10-13T06:00:00Z") or a phrase "in <number> <unit>" such as "in 10 min", "in 2 hours", "in 1 day". At most 30 days ahead; a time less than 5 seconds away (or up to one minute in the past) sends at once. scheduledAt is also accepted. |
to, cc and bcc together may hold at most 50 addresses. Each address is one
mailbox: lists in a single string (separated by commas or semicolons) are refused. Phrase units for
scheduled_at are s, sec, second, m,
min, minute, h, hr, hour, d and
day, singular or plural.
Attachment fields
| Name | Type | Description |
|---|---|---|
content required | string | The file, base64-encoded. |
filename | string | File name shown to the recipient, at most 255 characters, without slashes, backslashes or line breaks. |
content_type | string | Media type such as application/pdf, at most 255 characters (contentType is also accepted). |
content_id | string | Makes the attachment inline: reference it in html as cid:<content_id>. At most 100 letters, digits, dots, underscores, @ or dashes (contentId is also accepted). |
Attachments are sent as base64 content only; path and href (files fetched from
a URL or disk) are refused.
Request
curl -X POST https://send.tsmart.ai/emails \
-H "Authorization: Bearer $TSMART_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: welcome-user/123" \
-d '{
"from": "Acme <hello@yourdomain.com>",
"to": ["jane@example.com"],
"subject": "Welcome to Acme",
"html": "<p>Welcome aboard, Jane!</p>",
"reply_to": "support@yourdomain.com",
"tags": [{ "name": "category", "value": "welcome" }]
}' import { Tsmart } from "@tsmart/sdk";
const tsmart = new Tsmart(); // reads TSMART_API_KEY
const { data, error } = await tsmart.emails.send(
{
from: "Acme <hello@yourdomain.com>",
to: ["jane@example.com"],
subject: "Welcome to Acme",
html: "<p>Welcome aboard, Jane!</p>",
replyTo: "support@yourdomain.com",
tags: [{ name: "category", value: "welcome" }],
},
{ idempotencyKey: "welcome-user/123" },
);
if (error) throw new Error(`${error.name}: ${error.message}`);
console.log(data.id); from tsmart import Tsmart
client = Tsmart() # reads TSMART_API_KEY
email = client.emails.send(
{
"from": "Acme <hello@yourdomain.com>",
"to": ["jane@example.com"],
"subject": "Welcome to Acme",
"html": "<p>Welcome aboard, Jane!</p>",
"reply_to": "support@yourdomain.com",
"tags": [{"name": "category", "value": "welcome"}],
},
idempotency_key="welcome-user/123",
)
print(email["id"]) tsmart emails send \
--from "Acme <hello@yourdomain.com>" \
--to jane@example.com \
--subject "Welcome to Acme" \
--html "<p>Welcome aboard, Jane!</p>" \
--reply-to support@yourdomain.com \
--tag category=welcome \
--idempotency-key welcome-user/123 An inline image and a scheduled send:
curl -X POST https://send.tsmart.ai/emails \
-H "Authorization: Bearer $TSMART_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "Acme <hello@yourdomain.com>",
"to": "jane@example.com",
"subject": "Your October invoice",
"html": "<img src=\"cid:logo\" alt=\"Acme\"><p>Your invoice is attached.</p>",
"attachments": [
{ "filename": "logo.png", "content": "iVBORw0KGgoAAAANSUhEUgAA...", "content_type": "image/png", "content_id": "logo" },
{ "filename": "invoice-1042.pdf", "content": "JVBERi0xLjcKJcOkw7zDtsOf..." }
],
"scheduled_at": "in 2 hours"
}' Response
{
"id": "4ef9a417-02e9-4d39-ad75-9611e0fa6f60"
}
The id identifies the email in every other endpoint and in webhook payloads; the email's Message-ID header is
<id@your sending domain>. Recipients on your suppression list
are left out, each with an email.suppressed event; if no recipient is left, nothing is sent and the email
ends as suppressed, still with a 200 response.
A scheduled email records an email.scheduled event. When it is due, the hourly limits are checked again (an
email over the limit waits five more minutes); it is canceled if its API key was revoked meanwhile and fails if the
domain is no longer verified.
Errors
| Status | Name | When |
|---|---|---|
| 400 | invalid_idempotency_key | Idempotency-Key is not 1 to 256 characters. |
| 403 | invalid_from_address | The from domain is not one of your company's domains, its ownership is not proven yet, or the key is restricted to another domain. |
| 403 | domain_not_verified | Ownership of the domain is proven, but SPF and DKIM were not found at its last check (status pending or partially_verified). Publish them and call POST /domains/{id}/verify. |
| 403 | account_inactive | The company's subscription is not active. |
| 409 | invalid_idempotent_request | The idempotency key was used with a different body. |
| 409 | concurrent_idempotent_requests | A request with the same idempotency key is still running. |
| 413 | (not JSON) | The body is over 30 MB. This answer comes before the request reaches the API and has no JSON body. |
| 422 | missing_required_field | from, to or subject is missing. |
| 422 | validation_error | The body is not valid JSON ("Invalid JSON body"), not a JSON object, or a field is invalid: from is not exactly one address; a recipient is invalid; to is empty; more than 50 recipients; subject is empty or has a line break; neither html nor text; a NUL character; a header that is not allowed; bad tags; scheduled_at unreadable, in the past or more than 30 days ahead; attachments not an array or more than 20. template and topic_id are not supported and are refused. |
| 422 | invalid_attachment | An attachment has no base64 content, has an invalid filename, content_type or content_id, or uses path or href; or the attachments together exceed 20 MB after decoding ("Attachments exceed 20 MB"). |
| 429 | rate_limit_exceeded | An hourly recipient limit is reached ("Hourly sending limit reached"): the company's fair share or the shared platform-wide cap, which can answer before your own limits are reached. Or 20,000 recipients are already waiting in scheduled emails. Or, with retry-after, too many requests are in progress, or another request body over 2 MB of the company (or too many across the platform) is still being processed. |
| 429 | monthly_quota_exceeded | The plan's monthly allowance is used up. |
| 500 | application_error | The mail server did not accept the email ("The email could not be submitted"). The email is recorded as failed with an email.failed event. |
POST /emails/batch
Sends up to 100 emails in one call.
Permission: any key.
Headers
| Name | Type | Description |
|---|---|---|
x-batch-validation | string | strict (default): one invalid email refuses the whole batch. permissive: valid emails are sent and the invalid ones are listed in errors. |
Idempotency-Key | string | Optional, 1 to 256 characters; same rules as POST /emails. |
Body
A JSON array of 1 to 100 email objects with the same fields as POST /emails, except
attachments, which batch emails cannot have. Each email may have its own scheduled_at.
Request
curl -X POST https://send.tsmart.ai/emails/batch \
-H "Authorization: Bearer $TSMART_API_KEY" \
-H "Content-Type: application/json" \
-H "x-batch-validation: permissive" \
-d '[
{ "from": "Acme <hello@yourdomain.com>", "to": "jane@example.com", "subject": "Your order shipped", "text": "Order 1042 is on its way." },
{ "from": "Acme <hello@yourdomain.com>", "to": [], "subject": "Your order shipped", "text": "Order 1043 is on its way." }
]' const { data, error } = await tsmart.batch.send(
[
{ from: "Acme <hello@yourdomain.com>", to: "jane@example.com", subject: "Your order shipped", text: "Order 1042 is on its way." },
{ from: "Acme <hello@yourdomain.com>", to: "sam@example.com", subject: "Your order shipped", text: "Order 1043 is on its way." },
],
{ validation: "permissive", idempotencyKey: "shipping/2026-10-12" },
); result = client.batch.send(
[
{"from": "Acme <hello@yourdomain.com>", "to": "jane@example.com", "subject": "Your order shipped", "text": "Order 1042 is on its way."},
{"from": "Acme <hello@yourdomain.com>", "to": "sam@example.com", "subject": "Your order shipped", "text": "Order 1043 is on its way."},
],
validation="permissive",
idempotency_key="shipping/2026-10-12",
) tsmart batch send --file emails.json Response
The ids are in the order of the emails that were accepted. In strict mode the response has only data; in
permissive mode it also has errors, with the position of each refused email in your array.
{
"data": [
{ "id": "4ef9a417-02e9-4d39-ad75-9611e0fa6f60" }
],
"errors": [
{ "index": 1, "message": "`to` is required" }
]
} {
"data": [
{ "id": "4ef9a417-02e9-4d39-ad75-9611e0fa6f60" },
{ "id": "b81c3e55-6a0f-4b8e-9d21-3f7e0c5a92d4" }
]
}
Quota for the whole batch is reserved at once: if the accepted emails together exceed a limit, none is sent. When the
mail server refuses one email of a batch, that email is recorded as failed (with an email.failed event)
and its id is still returned. If no email of a permissive batch is valid, the response is
{ "data": [], "errors": [ … ] }.
Errors
| Status | Name | When |
|---|---|---|
| 422 | validation_error | The body is not valid JSON ("Invalid JSON body"), not an array of 1 to 100 emails, x-batch-validation is not strict or permissive, or (strict mode) an email is invalid, in which case the message starts with "Email at index N:". |
| 403, 422 | as in POST /emails | Strict mode: the first invalid email's error, with its status and name (invalid_from_address, domain_not_verified, missing_required_field, validation_error), prefixed with its index. An email with attachments gives validation_error. |
| 403 | account_inactive | The company's subscription is not active. |
| 400, 409 | idempotency errors | As in POST /emails. |
| 413 | (not JSON) | The body is over 30 MB; as in POST /emails. |
| 429 | rate_limit_exceeded, monthly_quota_exceeded | The batch would exceed an hourly limit (the company's fair share or the shared platform-wide cap), the scheduled limit or the monthly allowance; or, with retry-after, too many requests or large request bodies are in progress. |
GET /emails
Lists the company's emails, newest first.
Permission: full access; the key's creator needs the API controls privilege.
Query
| Name | Type | Description |
|---|---|---|
limit | integer | 1 to 100, default 20. |
after | string | An email id: return older emails. |
before | string | An email id: return newer emails. Use either after or before. |
Request
curl "https://send.tsmart.ai/emails?limit=2" \
-H "Authorization: Bearer $TSMART_API_KEY" Response
{
"object": "list",
"has_more": true,
"data": [
{
"object": "email",
"id": "4ef9a417-02e9-4d39-ad75-9611e0fa6f60",
"message_id": "<4ef9a417-02e9-4d39-ad75-9611e0fa6f60@yourdomain.com>",
"to": ["jane@example.com"],
"from": "Acme <hello@yourdomain.com>",
"created_at": "2026-10-12 09:15:02.431118+00",
"subject": "Welcome to Acme",
"bcc": null,
"cc": null,
"reply_to": ["support@yourdomain.com"],
"last_event": "delivered",
"scheduled_at": null
},
{
"object": "email",
"id": "b81c3e55-6a0f-4b8e-9d21-3f7e0c5a92d4",
"message_id": null,
"to": ["sam@example.com"],
"from": "Acme <hello@yourdomain.com>",
"created_at": "2026-10-12 09:02:47.906512+00",
"subject": "Your October invoice",
"bcc": null,
"cc": null,
"reply_to": null,
"last_event": "scheduled",
"scheduled_at": "2026-10-12 11:02:47.903000+00"
}
]
} The email object
| Name | Type | Description |
|---|---|---|
object | string | Always "email". |
id | string | Email id (UUID). |
message_id | string | null | The Message-ID header, <id@domain>; null until the email is handed to the mail server. |
to | string[] | Recipient addresses, lowercase, without display names. |
from | string | The sender as sent, with the display name if one was given. |
created_at | string | When the email was accepted. |
subject | string | Subject line. |
cc | string[] | null | In lists null when empty; GET /emails/{id} returns [] instead. |
bcc | string[] | null | Same as cc. |
reply_to | string[] | null | Same as cc. |
last_event | string | The latest thing that happened: scheduled, queued, sent, delivered, delivery_delayed, bounced, failed, canceled, suppressed, opened or clicked. |
scheduled_at | string | null | When a scheduled email is (or was) due; null for emails sent at once. |
html | string | null | GET /emails/{id} only. The HTML body while it is retained (3 days after sending), then null. |
text | string | null | GET /emails/{id} only. The text body you sent while it is retained; null if you sent none (a generated text part is not stored). |
tags | object[] | GET /emails/{id} only. The { name, value } pairs you sent. |
Errors
| Status | Name | When |
|---|---|---|
| 401 | restricted_api_key | A sending-access key. |
| 403 | invalid_permission | The key's creator lacks the API controls privilege. |
| 422 | validation_error | limit out of range, both after and before, or an invalid cursor. |
GET /emails/{id}
Returns one email with its tags and, while retained, its content.
Permission: full access; the key's creator needs the API controls privilege.
Path
| Name | Type | Description |
|---|---|---|
id required | string | The email id. |
Request
curl https://send.tsmart.ai/emails/4ef9a417-02e9-4d39-ad75-9611e0fa6f60 \
-H "Authorization: Bearer $TSMART_API_KEY" Response
{
"object": "email",
"id": "4ef9a417-02e9-4d39-ad75-9611e0fa6f60",
"message_id": "<4ef9a417-02e9-4d39-ad75-9611e0fa6f60@yourdomain.com>",
"to": ["jane@example.com"],
"from": "Acme <hello@yourdomain.com>",
"created_at": "2026-10-12 09:15:02.431118+00",
"subject": "Welcome to Acme",
"bcc": [],
"cc": [],
"reply_to": ["support@yourdomain.com"],
"last_event": "delivered",
"scheduled_at": null,
"html": "<p>Welcome aboard, Jane!</p>",
"text": null,
"tags": [{ "name": "category", "value": "welcome" }]
} Errors
| Status | Name | When |
|---|---|---|
| 401 | restricted_api_key | A sending-access key. |
| 403 | invalid_permission | The key's creator lacks the API controls privilege. |
| 404 | not_found | No email with this id in your company ("Email not found"). |
PATCH /emails/{id}
Moves a scheduled email to another time.
Permission: full access; the key's creator needs the API controls privilege.
Path
| Name | Type | Description |
|---|---|---|
id required | string | The email id. |
Body
| Name | Type | Description |
|---|---|---|
scheduled_at required | string | The new time, in the same formats as POST /emails: ISO 8601 with a time zone or a phrase such as "in 30 min". At most 30 days ahead. scheduledAt is also accepted. |
Request
curl -X PATCH https://send.tsmart.ai/emails/b81c3e55-6a0f-4b8e-9d21-3f7e0c5a92d4 \
-H "Authorization: Bearer $TSMART_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "scheduled_at": "2026-10-13T08:00:00+03:00" }' Response
{
"object": "email",
"id": "b81c3e55-6a0f-4b8e-9d21-3f7e0c5a92d4"
} Errors
| Status | Name | When |
|---|---|---|
| 401 | restricted_api_key | A sending-access key. |
| 403 | invalid_permission | The key's creator lacks the API controls privilege. |
| 404 | not_found | No email with this id in your company. |
| 422 | validation_error | scheduled_at is missing, unreadable, in the past or more than 30 days ahead, or the email is not (or no longer) scheduled: "Only a scheduled email that has not been sent can be updated". |
POST /emails/{id}/cancel
Cancels a scheduled email before it is sent.
Permission: full access; the key's creator needs the API controls privilege.
Path
| Name | Type | Description |
|---|---|---|
id required | string | The email id. |
Request
curl -X POST https://send.tsmart.ai/emails/b81c3e55-6a0f-4b8e-9d21-3f7e0c5a92d4/cancel \
-H "Authorization: Bearer $TSMART_API_KEY" Response
{
"object": "email",
"id": "b81c3e55-6a0f-4b8e-9d21-3f7e0c5a92d4"
}
The email's last_event becomes canceled and an email.canceled event is recorded.
Revoking an API key cancels its scheduled emails the same way.
Errors
| Status | Name | When |
|---|---|---|
| 401 | restricted_api_key | A sending-access key. |
| 403 | invalid_permission | The key's creator lacks the API controls privilege. |
| 404 | not_found | No email with this id in your company. |
| 422 | validation_error | The email is not (or no longer) scheduled: "Only a scheduled email that has not been sent can be canceled". |
GET /emails/{id}/events
Returns the event history of one email in time order, oldest first.
Permission: full access; the key's creator needs the API controls privilege.
Path
| Name | Type | Description |
|---|---|---|
id required | string | The email id. |
Query
| Name | Type | Description |
|---|---|---|
limit | integer | 1 to 100, default 20. |
after | string | An event id: return later events. |
before | string | An event id: return earlier events. Use either after or before. |
Request
curl https://send.tsmart.ai/emails/4ef9a417-02e9-4d39-ad75-9611e0fa6f60/events \
-H "Authorization: Bearer $TSMART_API_KEY" Response
{
"object": "list",
"has_more": false,
"data": [
{
"object": "email_event",
"id": "18342",
"type": "email.sent",
"created_at": "2026-10-12 09:15:02.617204+00",
"recipient": null
},
{
"object": "email_event",
"id": "18347",
"type": "email.delivered",
"created_at": "2026-10-12 09:15:04.999000+00",
"recipient": "jane@example.com",
"dsn": "2.0.0",
"message": "250 2.0.0 OK"
},
{
"object": "email_event",
"id": "18391",
"type": "email.opened",
"created_at": "2026-10-12 09:21:37.120455+00",
"recipient": null,
"ip_address": "203.0.113.24",
"user_agent": "ExampleMail/2.1"
}
]
} Event fields
| Name | Type | Description |
|---|---|---|
object | string | Always "email_event". |
id | string | Event id (a number as a string); use it as the after or before cursor. |
type | string | One of the event types below. |
created_at | string | When it happened. |
recipient | string | null | The recipient the event is about (delivery outcomes, suppressed); null for events of the whole email. |
dsn | string | Delivery status code from the receiving server, such as 2.0.0, 4.2.2 or 5.1.1. Only on delivery outcomes. |
message | string | The receiving server's reply. Only on delivery outcomes, and only when there is one. |
reason | string | Why the email failed, was canceled or a recipient was suppressed. |
link | string | The clicked URL (email.clicked). |
ip_address | string | Address of the opener or clicker (email.opened, email.clicked). |
user_agent | string | Their user agent (email.opened, email.clicked). |
Fields without a value are left out. The event types are:
| Type | Meaning |
|---|---|
email.scheduled | Accepted with a scheduled_at time. |
email.sent | Handed to the mail server. |
email.delivered | The recipient's server accepted it (one event per recipient). |
email.delivery_delayed | A temporary failure; delivery is retried. |
email.bounced | Delivery failed. A permanent failure (5.x.x) also adds the address to the suppression list. |
email.failed | The email could not be sent; reason says why. |
email.canceled | A scheduled email was canceled, by you or because its API key was revoked. |
email.suppressed | A recipient was skipped because it is on the suppression list. |
email.opened | The email was opened (open tracking on; at most one event per minute per email). |
email.clicked | A link was clicked (click tracking on; at most one event per minute per email and link). |
Errors
| Status | Name | When |
|---|---|---|
| 401 | restricted_api_key | A sending-access key. |
| 403 | invalid_permission | The key's creator lacks the API controls privilege. |
| 404 | not_found | No email with this id in your company. |
| 422 | validation_error | limit out of range, both after and before, or a cursor that is not an event of this email. |
GET /emails/metrics
Counts what happened to the emails sent in a time range: for each event type, how many of those emails had it, as totals and optionally per period and per sending domain.
Permission: full access; the key's creator needs the API controls privilege.
Query
| Name | Type | Description |
|---|---|---|
start_date | string | Start of the range: a date (2026-10-01, the start of that day in timezone), a local date and time (2026-10-01T08:00, read in timezone) or an instant (2026-10-01T08:00:00Z, 2026-10-01T08:00:00+03:00). Default: 7 days before end_date. |
end_date | string | End of the range, in the same formats. A date means the end of that day. Default and maximum: now. |
timezone | string | IANA time zone name such as Europe/Istanbul, used for dates, local times and periods. Default UTC. Abbreviations such as CET and offsets such as +03 are refused. |
granularity | string | Period length when dimensions includes period: hourly, daily (default), weekly or monthly. |
metrics | string | Comma-separated (or repeated) list of the metrics to return. Default: all of them. |
dimensions | string | Comma-separated (or repeated): period, domain or both. Without dimensions only totals are returned. |
domain_id | string | Comma-separated (or repeated) domain ids, at most 100: only count emails sent from these domains. |
Available metrics:
-
Counts:
sent,delivered,delivery_delayed,bounced,complained,failed,opened,clicked,suppressed,canceled,scheduled. Each is the number of emails that had at least one event of that type (an email counts once per type, however many recipients it had). -
Rates, between 0 and 1 with four decimals (0 when the base is 0):
delivery_rate= delivered / sent,bounce_rate= bounced / sent,open_rate= opened / delivered,click_rate= clicked / delivered.
Emails are placed in the range and in periods by the time they were sent (or created, if they have not been sent), so later events count toward the period of their email. The range may span at most 366 days and, with the period dimension, at most 10,000 periods. Weekly periods start on Monday; monthly periods on the first day of the month.
Request
curl "https://send.tsmart.ai/emails/metrics?start_date=2026-10-10&end_date=2026-10-11&timezone=Europe/Istanbul&metrics=sent,delivered,delivery_rate&dimensions=period" \
-H "Authorization: Bearer $TSMART_API_KEY" Response
{
"object": "metrics",
"start_date": "2026-10-09T21:00:00.000Z",
"end_date": "2026-10-11T20:59:59.999Z",
"timezone": "Europe/Istanbul",
"metrics": ["sent", "delivered", "delivery_rate"],
"dimensions": ["period"],
"granularity": "daily",
"totals": { "sent": 300, "delivered": 295, "delivery_rate": 0.9833 },
"data": [
{ "period": "2026-10-10", "sent": 180, "delivered": 177, "delivery_rate": 0.9833 },
{ "period": "2026-10-11", "sent": 120, "delivered": 118, "delivery_rate": 0.9833 }
]
} | Name | Type | Description |
|---|---|---|
object | string | Always "metrics". |
start_date, end_date | string | The resolved range as ISO 8601 instants in UTC. |
timezone, granularity | string | As used. |
metrics, dimensions | string[] | As used (duplicates removed). |
totals | object | Each requested metric for the whole range. |
data | object[] | Only with dimensions: one entry per period and/or domain that has events, sorted by period and domain name. period is YYYY-MM-DD (YYYY-MM-DDTHH:MM:SS for hourly) in timezone; domain_id and domain_name are null for a domain that no longer exists. |
Errors
| Status | Name | When |
|---|---|---|
| 401 | restricted_api_key | A sending-access key. |
| 403 | invalid_permission | The key's creator lacks the API controls privilege. |
| 422 | validation_error | An invalid date, time zone, granularity, metric, dimension or domain id; start_date after end_date; a range over 366 days or over 10,000 periods; email_id or broadcast_id given; or a range too large to count in time ("narrow the dates or filter by domain_id"). |
| 429 | rate_limit_exceeded | Another metrics request of your company is still running. Only one runs at a time. |