The Mail area publishes 58 REST endpoints. Paths are relative to https://api.lepsto.com; see Authentication for the required header.
GET/mail/api-keys
List active API keys (prefix + metadata only, never the secret)
MCP tool: mail_apikey_list
Parameters
No parameters.
Response
Returns object[].
| Item field | Type | Always | Description |
|---|
id | string (uuid)
| • | API key id; pass it to mail_apikey_delete to revoke the key |
name | string
| • | Human-readable label given when the key was issued |
scope | stringone of: full_access, sending_access
| • | Permission scope: full_access can call every mail tool, sending_access can only send email |
prefix | string
| • | Opening characters of the secret, so a key can be recognised in a log or a header |
domainId | string (uuid) | null
| • | Sending domain this key is locked to; null if it may send from any verified domain |
createdAt | string (date-time)
| • | When the key was issued (ISO 8601 UTC) |
POST/mail/api-keys
Issue a scoped sending API key; the full secret is returned only once
MCP tool: mail_apikey_create
Parameters
| Name | In | Type | Required | Description |
|---|
name | body | string
| • | Human-readable label for the key, e.g. "production sender" |
scope | body | stringone of: full_access, sending_access
| • | Permission scope: full_access can call every mail tool, sending_access can only send email |
domainId | body | string (uuid)
| — | Lock the key to this sending domain; omit to let it send from any verified domain |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | API key id; pass it to mail_apikey_delete to revoke the key |
key | string
| • | The full secret. Returned only by this call and never retrievable again — store it now |
name | string
| • | Human-readable label given when the key was issued |
scope | stringone of: full_access, sending_access
| • | Permission scope: full_access can call every mail tool, sending_access can only send email |
prefix | string
| • | Opening characters of the secret, so a key can be recognised in a log or a header |
domainId | string (uuid) | null
| • | Sending domain this key is locked to; null if it may send from any verified domain |
createdAt | string (date-time)
| • | When the key was issued (ISO 8601 UTC) |
DELETE/mail/api-keys/:id
Revoke an API key by id
MCP tool: mail_apikey_delete
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Id of the API key to revoke; revocation is immediate and permanent |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Id of the key that was revoked |
revoked | booleanone of: true
| • | Always true; the call throws rather than reporting a failure here |
GET/mail/audiences
List audiences for the current product
MCP tool: mail_audience_list
Parameters
No parameters.
Response
Returns object[].
| Item field | Type | Always | Description |
|---|
id | string (uuid)
| • | Audience id |
name | string
| • | Human label for the audience |
createdAt | string (date-time)
| • | When the audience was created (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the audience was last modified (ISO 8601 UTC) |
POST/mail/audiences
Create an audience (a named bucket of contacts) for the current product
MCP tool: mail_audience_create
Parameters
| Name | In | Type | Required | Description |
|---|
name | body | string
| • | Human label for the audience |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Audience id |
name | string
| • | Human label for the audience |
createdAt | string (date-time)
| • | When the audience was created (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the audience was last modified (ISO 8601 UTC) |
GET/mail/audiences/:audienceId/contacts
List contacts in an audience
MCP tool: mail_contact_list
Parameters
| Name | In | Type | Required | Description |
|---|
audience_id | query | string (uuid)
| • | Audience to list contacts from |
unsubscribed | query | string | booleanone of: true, false
| — | Filter by unsubscribed flag |
cursor | query | string
| — | Opaque pagination cursor from a prior page; omit for the first page |
limit | query | integer
| — | Max items per page (1–100, default 50) |
audienceId | path | string
| — | — |
Response
Returns object.
| Field | Type | Always | Description |
|---|
data | object[]
| • | Contacts on this page, newest first |
nextCursor | string | null
| • | Cursor for the next page; null on the last page |
POST/mail/audiences/:audienceId/contacts
Add a contact to an audience
MCP tool: mail_contact_create
Parameters
| Name | In | Type | Required | Description |
|---|
audience_id | body | string (uuid)
| • | Audience the contact belongs to |
email | body | string
| • | Contact email address |
properties | body | object
| — | Custom key/value properties (e.g. first_name, last_name) |
unsubscribed | body | boolean
| — | Marketing opt-out flag |
audienceId | path | string
| — | — |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Contact id |
email | string
| • | Contact email address, normalized to lowercase |
createdAt | string (date-time)
| • | When the contact was created (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the contact was last modified (ISO 8601 UTC) |
audienceId | string (uuid)
| • | Audience the contact belongs to |
properties | null
| — | Custom key/value properties (e.g. first_name, last_name) |
unsubscribed | boolean
| • | Marketing opt-out flag for this audience |
DELETE/mail/audiences/:audienceId/contacts/:id
Delete a contact from an audience
MCP tool: mail_contact_delete
Parameters
| Name | In | Type | Required | Description |
|---|
audience_id | body | string (uuid)
| • | Audience id |
id | path | string (uuid)
| • | Contact id |
audienceId | path | string
| — | — |
Response
Returns object.
| Field | Type | Always | Description |
|---|
deleted | boolean
| • | True once the contact is gone |
GET/mail/audiences/:audienceId/contacts/:id
Get a single contact by id
MCP tool: mail_contact_get
Parameters
| Name | In | Type | Required | Description |
|---|
audience_id | body | string (uuid)
| • | Audience id |
id | path | string (uuid)
| • | Contact id |
audienceId | path | string
| — | — |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Contact id |
email | string
| • | Contact email address, normalized to lowercase |
createdAt | string (date-time)
| • | When the contact was created (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the contact was last modified (ISO 8601 UTC) |
audienceId | string (uuid)
| • | Audience the contact belongs to |
properties | null
| — | Custom key/value properties (e.g. first_name, last_name) |
unsubscribed | boolean
| • | Marketing opt-out flag for this audience |
PATCH/mail/audiences/:audienceId/contacts/:id
Update a contact (properties or unsubscribed flag)
MCP tool: mail_contact_update
Parameters
| Name | In | Type | Required | Description |
|---|
audience_id | body | string (uuid)
| • | Audience id |
id | path | string (uuid)
| • | Contact id |
properties | body | object
| — | Replace the custom properties object |
unsubscribed | body | boolean
| — | Set the marketing opt-out flag |
audienceId | path | string
| — | — |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Contact id |
email | string
| • | Contact email address, normalized to lowercase |
createdAt | string (date-time)
| • | When the contact was created (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the contact was last modified (ISO 8601 UTC) |
audienceId | string (uuid)
| • | Audience the contact belongs to |
properties | null
| — | Custom key/value properties (e.g. first_name, last_name) |
unsubscribed | boolean
| • | Marketing opt-out flag for this audience |
DELETE/mail/audiences/:id
Delete an audience and all its contacts (cascade)
MCP tool: mail_audience_delete
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Audience id to delete |
Response
Returns object.
| Field | Type | Always | Description |
|---|
deleted | boolean
| • | True once the audience and its contacts are gone |
GET/mail/audiences/:id
Get a single audience by id
MCP tool: mail_audience_get
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Audience id |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Audience id |
name | string
| • | Human label for the audience |
createdAt | string (date-time)
| • | When the audience was created (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the audience was last modified (ISO 8601 UTC) |
PATCH/mail/audiences/:id
Rename an audience
MCP tool: mail_audience_update
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Audience id |
name | body | string
| — | New name |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Audience id |
name | string
| • | Human label for the audience |
createdAt | string (date-time)
| • | When the audience was created (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the audience was last modified (ISO 8601 UTC) |
GET/mail/broadcasts
List broadcasts for the product (cursor-paginated)
MCP tool: mail_broadcast_list
Parameters
| Name | In | Type | Required | Description |
|---|
cursor | query | string
| — | Opaque cursor from the previous page’s `nextCursor`. Omit for the first page. |
limit | query | integer
| — | Page size, 1-100. Defaults to 50. |
Response
Returns object.
| Field | Type | Always | Description |
|---|
items | object[]
| • | The broadcasts on this page, newest first |
nextCursor | string | null
| • | Pass as `cursor` for the next page; null on the last page |
POST/mail/broadcasts
Create a draft broadcast (inline content or a template reference) targeting an audience
MCP tool: mail_broadcast_create
Parameters
| Name | In | Type | Required | Description |
|---|
name | body | string
| • | Internal label for the broadcast — never shown to recipients |
audienceId | body | string (uuid)
| • | Audience whose subscribed contacts receive this broadcast |
from | body | string
| • | Sender on a verified domain, e.g. "Name <you@your-domain.com>" |
replyTo | body | string[]
| — | Reply-To addresses. Defaults to [] — replies go to `from`. |
headers | body | object
| — | Custom MIME headers added to every message. Defaults to {}. |
subject | body | string
| — | Subject line, capped at the RFC-5322 line limit. Required with inline content, forbidden with a template. |
html | body | string
| — | HTML body. Inline content only — forbidden with a template. |
text | body | string
| — | Plain-text body. Inline content only — forbidden with a template. |
template | body | object
| — | Send by reference to a published template instead of inline content |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Broadcast id |
from | string
| • | Sender the messages are sent as |
html | string | null
| • | Inline HTML body; null when a template supplies it |
name | string
| • | Internal label — never shown to recipients |
text | string | null
| • | Inline plain-text body; null when a template supplies it |
sentAt | string (date-time) | null
| • | When the last message left; null until sending finishes |
status | stringone of: draft, queued, sent, failed, canceled
| • | Lifecycle state: draft (editable), queued (fanned out, sending), sent, failed, canceled |
headers | object
| • | Custom MIME headers added to every message |
replyTo | string[]
| • | Reply-To addresses; empty when replies go to `from` |
subject | string | null
| • | Subject line for inline content; null when a template supplies it |
queuedAt | string (date-time) | null
| • | When the broadcast was queued; null while it is a draft |
createdAt | string (date-time)
| • | When the broadcast was created |
lastError | string | null
| • | Why the broadcast failed; null unless status is failed |
productId | string
| • | Product the broadcast belongs to |
updatedAt | string (date-time)
| • | When the broadcast was last modified |
variables | object | null
| • | Values passed to the template variables; {} for inline content |
audienceId | string (uuid)
| • | Audience whose contacts this broadcast is sent to |
templateId | string | null
| • | Template rendered for every recipient; null for inline content |
recipientCount | integer
| • | Contacts the broadcast fanned out to; 0 while it is still a draft |
DELETE/mail/broadcasts/:id
Delete a draft broadcast
MCP tool: mail_broadcast_delete
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Broadcast id |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Id of the deleted broadcast |
deleted | boolean
| • | True when the broadcast was removed |
GET/mail/broadcasts/:id
Get one broadcast by id
MCP tool: mail_broadcast_get
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Broadcast id |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Broadcast id |
from | string
| • | Sender the messages are sent as |
html | string | null
| • | Inline HTML body; null when a template supplies it |
name | string
| • | Internal label — never shown to recipients |
text | string | null
| • | Inline plain-text body; null when a template supplies it |
sentAt | string (date-time) | null
| • | When the last message left; null until sending finishes |
status | stringone of: draft, queued, sent, failed, canceled
| • | Lifecycle state: draft (editable), queued (fanned out, sending), sent, failed, canceled |
headers | object
| • | Custom MIME headers added to every message |
replyTo | string[]
| • | Reply-To addresses; empty when replies go to `from` |
subject | string | null
| • | Subject line for inline content; null when a template supplies it |
queuedAt | string (date-time) | null
| • | When the broadcast was queued; null while it is a draft |
createdAt | string (date-time)
| • | When the broadcast was created |
lastError | string | null
| • | Why the broadcast failed; null unless status is failed |
productId | string
| • | Product the broadcast belongs to |
updatedAt | string (date-time)
| • | When the broadcast was last modified |
variables | object | null
| • | Values passed to the template variables; {} for inline content |
audienceId | string (uuid)
| • | Audience whose contacts this broadcast is sent to |
templateId | string | null
| • | Template rendered for every recipient; null for inline content |
recipientCount | integer
| • | Contacts the broadcast fanned out to; 0 while it is still a draft |
PATCH/mail/broadcasts/:id
Edit a draft broadcast
MCP tool: mail_broadcast_update
Parameters
| Name | In | Type | Required | Description |
|---|
name | body | string
| — | Internal label for the broadcast — never shown to recipients |
audienceId | body | string (uuid)
| — | Audience whose subscribed contacts receive this broadcast |
from | body | string
| — | Sender on a verified domain, e.g. "Name <you@your-domain.com>" |
replyTo | body | string[]
| — | Reply-To addresses. Defaults to [] — replies go to `from`. |
headers | body | object
| — | Custom MIME headers added to every message. Defaults to {}. |
subject | body | string
| — | Subject line, capped at the RFC-5322 line limit. Required with inline content, forbidden with a template. |
html | body | string
| — | HTML body. Inline content only — forbidden with a template. |
text | body | string
| — | Plain-text body. Inline content only — forbidden with a template. |
template | body | object
| — | Send by reference to a published template instead of inline content |
id | path | string (uuid)
| • | Broadcast id |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Broadcast id |
from | string
| • | Sender the messages are sent as |
html | string | null
| • | Inline HTML body; null when a template supplies it |
name | string
| • | Internal label — never shown to recipients |
text | string | null
| • | Inline plain-text body; null when a template supplies it |
sentAt | string (date-time) | null
| • | When the last message left; null until sending finishes |
status | stringone of: draft, queued, sent, failed, canceled
| • | Lifecycle state: draft (editable), queued (fanned out, sending), sent, failed, canceled |
headers | object
| • | Custom MIME headers added to every message |
replyTo | string[]
| • | Reply-To addresses; empty when replies go to `from` |
subject | string | null
| • | Subject line for inline content; null when a template supplies it |
queuedAt | string (date-time) | null
| • | When the broadcast was queued; null while it is a draft |
createdAt | string (date-time)
| • | When the broadcast was created |
lastError | string | null
| • | Why the broadcast failed; null unless status is failed |
productId | string
| • | Product the broadcast belongs to |
updatedAt | string (date-time)
| • | When the broadcast was last modified |
variables | object | null
| • | Values passed to the template variables; {} for inline content |
audienceId | string (uuid)
| • | Audience whose contacts this broadcast is sent to |
templateId | string | null
| • | Template rendered for every recipient; null for inline content |
recipientCount | integer
| • | Contacts the broadcast fanned out to; 0 while it is still a draft |
POST/mail/broadcasts/:id/cancel
Cancel a draft or queued broadcast
MCP tool: mail_broadcast_cancel
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Broadcast id |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Broadcast id |
from | string
| • | Sender the messages are sent as |
html | string | null
| • | Inline HTML body; null when a template supplies it |
name | string
| • | Internal label — never shown to recipients |
text | string | null
| • | Inline plain-text body; null when a template supplies it |
sentAt | string (date-time) | null
| • | When the last message left; null until sending finishes |
status | stringone of: draft, queued, sent, failed, canceled
| • | Lifecycle state: draft (editable), queued (fanned out, sending), sent, failed, canceled |
headers | object
| • | Custom MIME headers added to every message |
replyTo | string[]
| • | Reply-To addresses; empty when replies go to `from` |
subject | string | null
| • | Subject line for inline content; null when a template supplies it |
queuedAt | string (date-time) | null
| • | When the broadcast was queued; null while it is a draft |
createdAt | string (date-time)
| • | When the broadcast was created |
lastError | string | null
| • | Why the broadcast failed; null unless status is failed |
productId | string
| • | Product the broadcast belongs to |
updatedAt | string (date-time)
| • | When the broadcast was last modified |
variables | object | null
| • | Values passed to the template variables; {} for inline content |
audienceId | string (uuid)
| • | Audience whose contacts this broadcast is sent to |
templateId | string | null
| • | Template rendered for every recipient; null for inline content |
recipientCount | integer
| • | Contacts the broadcast fanned out to; 0 while it is still a draft |
POST/mail/broadcasts/:id/queue
Queue a draft broadcast — fans out one email per eligible contact
MCP tool: mail_broadcast_queue
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Broadcast id |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Broadcast id |
from | string
| • | Sender the messages are sent as |
html | string | null
| • | Inline HTML body; null when a template supplies it |
name | string
| • | Internal label — never shown to recipients |
text | string | null
| • | Inline plain-text body; null when a template supplies it |
sentAt | string (date-time) | null
| • | When the last message left; null until sending finishes |
status | stringone of: draft, queued, sent, failed, canceled
| • | Lifecycle state: draft (editable), queued (fanned out, sending), sent, failed, canceled |
headers | object
| • | Custom MIME headers added to every message |
replyTo | string[]
| • | Reply-To addresses; empty when replies go to `from` |
subject | string | null
| • | Subject line for inline content; null when a template supplies it |
queuedAt | string (date-time) | null
| • | When the broadcast was queued; null while it is a draft |
createdAt | string (date-time)
| • | When the broadcast was created |
lastError | string | null
| • | Why the broadcast failed; null unless status is failed |
productId | string
| • | Product the broadcast belongs to |
updatedAt | string (date-time)
| • | When the broadcast was last modified |
variables | object | null
| • | Values passed to the template variables; {} for inline content |
audienceId | string (uuid)
| • | Audience whose contacts this broadcast is sent to |
templateId | string | null
| • | Template rendered for every recipient; null for inline content |
recipientCount | integer
| • | Contacts the broadcast fanned out to; 0 while it is still a draft |
GET/mail/broadcasts/:id/stats
Per-broadcast analytics: recipients/suppressed/failed + delivered/opened/clicked/bounced
MCP tool: mail_broadcast_stats
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Broadcast id |
Response
Returns object.
| Field | Type | Always | Description |
|---|
failed | integer
| • | Messages that could not be handed to the provider |
opened | integer
| • | Messages opened at least once, as seen by the tracking pixel |
bounced | integer
| • | Messages that bounced, hard or soft |
clicked | integer
| • | Messages with at least one tracked link click |
delivered | integer
| • | Messages the receiving server accepted |
recipients | integer
| • | Contacts the broadcast fanned out to |
suppressed | integer
| • | Recipients skipped because they are on the suppression list |
GET/mail/domains
List sending domains for the current product
MCP tool: mail_domain_list
Parameters
No parameters.
Response
Returns object[].
| Item field | Type | Always | Description |
|---|
id | string (uuid)
| • | Sending domain id |
tls | stringone of: opportunistic, enforced
| • | TLS policy for delivery: opportunistic falls back to plaintext if the recipient offers no TLS, enforced fails the send instead |
apex | string | null
| • | Governed apex this domain sits under; null if it is not governed |
mode | string | nullone of: external, managed
| • | Who operates DNS: managed if the platform publishes the records for you, external if you publish them yourself; null if the domain is not governed |
name | string
| • | The sending domain itself, e.g. "example.com" |
active | boolean
| • | True only when the domain is verified AND its governance binding is active — the condition for sending from it |
region | string
| • | AWS region hosting the SES identity, which fixes data residency; set at create time and immutable |
status | stringone of: not_started, pending, verified, failed, temporary_failure
| • | SES verification state: not_started before the first check, pending while DNS propagates, verified once sending is allowed, failed or temporary_failure when SES could not verify |
records | object[]
| • | DNS records to publish for this domain, each with its last-seen resolution status |
createdAt | string (date-time)
| • | When the domain was registered (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the domain record was last changed (ISO 8601 UTC) |
verifiedAt | string (date-time) | null
| • | When the domain became verified (ISO 8601 UTC); null while it is not |
instructions | string[]
| • | Human-readable steps still outstanding before this domain can send |
openTracking | boolean
| • | True if a 1x1 pixel is injected into outgoing mail to record opens |
bindingStatus | stringone of: pending, active, failed
| • | Governance binding state: pending while it is being granted, active once the domain may be used, failed if it could not be granted |
clickTracking | boolean
| • | True if links are rewritten through the tracking host to record clicks |
dmarcBindingId | string | null
| • | Id of the separate binding that publishes this domain's DMARC record; null on external domains, which publish DMARC themselves, and when the _dmarc host could not be claimed |
customReturnPath | string
| • | Host used as the bounce (Return-Path) address, so bounces come back to this product |
trackingSubdomain | string | null
| • | Host serving the click redirect and the open pixel; null if tracking is off |
governanceDomainId | string | null
| • | Id of the governance domain this one is registered under; null if it is not governed |
governanceBindingId | string | null
| • | Id of the binding between this product and the governance domain; null if unbound |
verificationStartedAt | string (date-time)
| • | When verification was first requested (ISO 8601 UTC) |
lastVerificationCheckAt | string (date-time) | null
| • | When DNS and SES were last checked (ISO 8601 UTC); null if no check has run yet |
POST/mail/domains
Register a sending domain (SES Easy DKIM) and return the DNS records to publish
MCP tool: mail_domain_create
Parameters
| Name | In | Type | Required | Description |
|---|
name | body | string
| • | The sending domain to register, e.g. "example.com"; it must sit under an apex this product is allowed to use (see mail_domain_allowed_list) |
region | body | string
| — | AWS region for the SES identity, which fixes data residency (default "eu-north-1"); immutable once the domain is created |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Sending domain id |
tls | stringone of: opportunistic, enforced
| • | TLS policy for delivery: opportunistic falls back to plaintext if the recipient offers no TLS, enforced fails the send instead |
apex | string | null
| • | Governed apex this domain sits under; null if it is not governed |
mode | string | nullone of: external, managed
| • | Who operates DNS: managed if the platform publishes the records for you, external if you publish them yourself; null if the domain is not governed |
name | string
| • | The sending domain itself, e.g. "example.com" |
active | boolean
| • | True only when the domain is verified AND its governance binding is active — the condition for sending from it |
region | string
| • | AWS region hosting the SES identity, which fixes data residency; set at create time and immutable |
status | stringone of: not_started, pending, verified, failed, temporary_failure
| • | SES verification state: not_started before the first check, pending while DNS propagates, verified once sending is allowed, failed or temporary_failure when SES could not verify |
records | object[]
| • | DNS records to publish for this domain, each with its last-seen resolution status |
createdAt | string (date-time)
| • | When the domain was registered (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the domain record was last changed (ISO 8601 UTC) |
verifiedAt | string (date-time) | null
| • | When the domain became verified (ISO 8601 UTC); null while it is not |
instructions | string[]
| • | Human-readable steps still outstanding before this domain can send |
openTracking | boolean
| • | True if a 1x1 pixel is injected into outgoing mail to record opens |
bindingStatus | stringone of: pending, active, failed
| • | Governance binding state: pending while it is being granted, active once the domain may be used, failed if it could not be granted |
clickTracking | boolean
| • | True if links are rewritten through the tracking host to record clicks |
dmarcBindingId | string | null
| • | Id of the separate binding that publishes this domain's DMARC record; null on external domains, which publish DMARC themselves, and when the _dmarc host could not be claimed |
customReturnPath | string
| • | Host used as the bounce (Return-Path) address, so bounces come back to this product |
trackingSubdomain | string | null
| • | Host serving the click redirect and the open pixel; null if tracking is off |
governanceDomainId | string | null
| • | Id of the governance domain this one is registered under; null if it is not governed |
governanceBindingId | string | null
| • | Id of the binding between this product and the governance domain; null if unbound |
verificationStartedAt | string (date-time)
| • | When verification was first requested (ISO 8601 UTC) |
lastVerificationCheckAt | string (date-time) | null
| • | When DNS and SES were last checked (ISO 8601 UTC); null if no check has run yet |
DELETE/mail/domains/:id
Delete a sending domain and its SES identity
MCP tool: mail_domain_delete
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Sending domain to delete, along with its SES identity |
Response
Returns object.
| Field | Type | Always | Description |
|---|
deleted | boolean
| • | True once the domain and its SES identity are gone |
GET/mail/domains/:id
Get a sending domain with its DNS records and per-record verification status
MCP tool: mail_domain_get
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Sending domain id |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Sending domain id |
tls | stringone of: opportunistic, enforced
| • | TLS policy for delivery: opportunistic falls back to plaintext if the recipient offers no TLS, enforced fails the send instead |
apex | string | null
| • | Governed apex this domain sits under; null if it is not governed |
mode | string | nullone of: external, managed
| • | Who operates DNS: managed if the platform publishes the records for you, external if you publish them yourself; null if the domain is not governed |
name | string
| • | The sending domain itself, e.g. "example.com" |
active | boolean
| • | True only when the domain is verified AND its governance binding is active — the condition for sending from it |
region | string
| • | AWS region hosting the SES identity, which fixes data residency; set at create time and immutable |
status | stringone of: not_started, pending, verified, failed, temporary_failure
| • | SES verification state: not_started before the first check, pending while DNS propagates, verified once sending is allowed, failed or temporary_failure when SES could not verify |
records | object[]
| • | DNS records to publish for this domain, each with its last-seen resolution status |
createdAt | string (date-time)
| • | When the domain was registered (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the domain record was last changed (ISO 8601 UTC) |
verifiedAt | string (date-time) | null
| • | When the domain became verified (ISO 8601 UTC); null while it is not |
instructions | string[]
| • | Human-readable steps still outstanding before this domain can send |
openTracking | boolean
| • | True if a 1x1 pixel is injected into outgoing mail to record opens |
bindingStatus | stringone of: pending, active, failed
| • | Governance binding state: pending while it is being granted, active once the domain may be used, failed if it could not be granted |
clickTracking | boolean
| • | True if links are rewritten through the tracking host to record clicks |
dmarcBindingId | string | null
| • | Id of the separate binding that publishes this domain's DMARC record; null on external domains, which publish DMARC themselves, and when the _dmarc host could not be claimed |
customReturnPath | string
| • | Host used as the bounce (Return-Path) address, so bounces come back to this product |
trackingSubdomain | string | null
| • | Host serving the click redirect and the open pixel; null if tracking is off |
governanceDomainId | string | null
| • | Id of the governance domain this one is registered under; null if it is not governed |
governanceBindingId | string | null
| • | Id of the binding between this product and the governance domain; null if unbound |
verificationStartedAt | string (date-time)
| • | When verification was first requested (ISO 8601 UTC) |
lastVerificationCheckAt | string (date-time) | null
| • | When DNS and SES were last checked (ISO 8601 UTC); null if no check has run yet |
PATCH/mail/domains/:id
Update tracking / TLS / return-path config for a domain
MCP tool: mail_domain_update
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Sending domain id |
openTracking | body | boolean
| — | Record opens by injecting a 1x1 pixel (off by default); omit to leave it unchanged |
clickTracking | body | boolean
| — | Record clicks by rewriting links through the tracking host (off by default); omit to leave it unchanged |
trackingSubdomain | body | string | null
| — | Host to serve the click redirect and open pixel from, or null to clear it; omit to leave it unchanged |
tls | body | stringone of: opportunistic, enforced
| — | TLS policy: opportunistic (default) falls back to plaintext, enforced fails the send instead; omit to leave it unchanged |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Sending domain id |
tls | stringone of: opportunistic, enforced
| • | TLS policy for delivery: opportunistic falls back to plaintext if the recipient offers no TLS, enforced fails the send instead |
apex | string | null
| • | Governed apex this domain sits under; null if it is not governed |
mode | string | nullone of: external, managed
| • | Who operates DNS: managed if the platform publishes the records for you, external if you publish them yourself; null if the domain is not governed |
name | string
| • | The sending domain itself, e.g. "example.com" |
active | boolean
| • | True only when the domain is verified AND its governance binding is active — the condition for sending from it |
region | string
| • | AWS region hosting the SES identity, which fixes data residency; set at create time and immutable |
status | stringone of: not_started, pending, verified, failed, temporary_failure
| • | SES verification state: not_started before the first check, pending while DNS propagates, verified once sending is allowed, failed or temporary_failure when SES could not verify |
records | object[]
| • | DNS records to publish for this domain, each with its last-seen resolution status |
createdAt | string (date-time)
| • | When the domain was registered (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the domain record was last changed (ISO 8601 UTC) |
verifiedAt | string (date-time) | null
| • | When the domain became verified (ISO 8601 UTC); null while it is not |
instructions | string[]
| • | Human-readable steps still outstanding before this domain can send |
openTracking | boolean
| • | True if a 1x1 pixel is injected into outgoing mail to record opens |
bindingStatus | stringone of: pending, active, failed
| • | Governance binding state: pending while it is being granted, active once the domain may be used, failed if it could not be granted |
clickTracking | boolean
| • | True if links are rewritten through the tracking host to record clicks |
dmarcBindingId | string | null
| • | Id of the separate binding that publishes this domain's DMARC record; null on external domains, which publish DMARC themselves, and when the _dmarc host could not be claimed |
customReturnPath | string
| • | Host used as the bounce (Return-Path) address, so bounces come back to this product |
trackingSubdomain | string | null
| • | Host serving the click redirect and the open pixel; null if tracking is off |
governanceDomainId | string | null
| • | Id of the governance domain this one is registered under; null if it is not governed |
governanceBindingId | string | null
| • | Id of the binding between this product and the governance domain; null if unbound |
verificationStartedAt | string (date-time)
| • | When verification was first requested (ISO 8601 UTC) |
lastVerificationCheckAt | string (date-time) | null
| • | When DNS and SES were last checked (ISO 8601 UTC); null if no check has run yet |
POST/mail/domains/:id/verify
Re-check a domain's DNS + SES verification immediately
MCP tool: mail_domain_verify
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Sending domain to re-check against DNS and SES right now, instead of waiting for the next scheduled check |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Sending domain id |
tls | stringone of: opportunistic, enforced
| • | TLS policy for delivery: opportunistic falls back to plaintext if the recipient offers no TLS, enforced fails the send instead |
apex | string | null
| • | Governed apex this domain sits under; null if it is not governed |
mode | string | nullone of: external, managed
| • | Who operates DNS: managed if the platform publishes the records for you, external if you publish them yourself; null if the domain is not governed |
name | string
| • | The sending domain itself, e.g. "example.com" |
active | boolean
| • | True only when the domain is verified AND its governance binding is active — the condition for sending from it |
region | string
| • | AWS region hosting the SES identity, which fixes data residency; set at create time and immutable |
status | stringone of: not_started, pending, verified, failed, temporary_failure
| • | SES verification state: not_started before the first check, pending while DNS propagates, verified once sending is allowed, failed or temporary_failure when SES could not verify |
records | object[]
| • | DNS records to publish for this domain, each with its last-seen resolution status |
createdAt | string (date-time)
| • | When the domain was registered (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the domain record was last changed (ISO 8601 UTC) |
verifiedAt | string (date-time) | null
| • | When the domain became verified (ISO 8601 UTC); null while it is not |
instructions | string[]
| • | Human-readable steps still outstanding before this domain can send |
openTracking | boolean
| • | True if a 1x1 pixel is injected into outgoing mail to record opens |
bindingStatus | stringone of: pending, active, failed
| • | Governance binding state: pending while it is being granted, active once the domain may be used, failed if it could not be granted |
clickTracking | boolean
| • | True if links are rewritten through the tracking host to record clicks |
dmarcBindingId | string | null
| • | Id of the separate binding that publishes this domain's DMARC record; null on external domains, which publish DMARC themselves, and when the _dmarc host could not be claimed |
customReturnPath | string
| • | Host used as the bounce (Return-Path) address, so bounces come back to this product |
trackingSubdomain | string | null
| • | Host serving the click redirect and the open pixel; null if tracking is off |
governanceDomainId | string | null
| • | Id of the governance domain this one is registered under; null if it is not governed |
governanceBindingId | string | null
| • | Id of the binding between this product and the governance domain; null if unbound |
verificationStartedAt | string (date-time)
| • | When verification was first requested (ISO 8601 UTC) |
lastVerificationCheckAt | string (date-time) | null
| • | When DNS and SES were last checked (ISO 8601 UTC); null if no check has run yet |
GET/mail/domains/allowed
List apex domains this product may register sending domains under (from governance)
MCP tool: mail_domain_allowed_list
Parameters
No parameters.
Response
Returns object[].
| Item field | Type | Always | Description |
|---|
mode | stringone of: external, managed
| • | Who operates DNS under this apex: managed if the platform publishes the records, external if you do |
domain | string
| • | The apex domain itself, e.g. "example.com" |
domainId | string
| • | Governance domain id — pass it to the governance console, not to mail_domain_get |
extensionCount | integer
| • | How many extensions currently send under this apex |
GET/mail/emails
List this product’s emails, newest first. Filter by recipient, status, sender domain, subject, template or creation time; paginate with nextCursor. Use mail_email_get for last_event.
MCP tool: mail_email_list
Parameters
| Name | In | Type | Required | Description |
|---|
status | query | stringone of: scheduled, queued, sent, failed, canceled, delivered, bounced, complained, suppressed, blocked
| — | Filter by email status |
to | query | string
| — | Filter by a recipient address |
domain | query | string
| — | Filter by sender domain |
after | query | string (date-time)
| — | ISO-8601 lower bound on created_at (inclusive) |
before | query | string (date-time)
| — | ISO-8601 upper bound on created_at (exclusive) |
q | query | string
| — | Case-insensitive subject search |
template_id | query | string (uuid)
| — | Filter by the template the email was rendered from |
limit | query | integer
| — | Page size, 1-100. Defaults to 25. |
cursor | query | string
| — | Opaque cursor from the previous page’s `nextCursor`. Omit for the first page. |
Response
Returns object.
| Field | Type | Always | Description |
|---|
items | object[]
| • | Emails in descending creation order |
nextCursor | string | null
| • | Opaque cursor for the next page; null at the end |
POST/mail/emails
Send a single email
MCP tool: mail_email_send
Parameters
| Name | In | Type | Required | Description |
|---|
from | body | string
| • | Sender on a verified domain, e.g. "Name <you@your-domain.com>" |
to | body | string | string[]
| — | Primary recipient(s) |
cc | body | string | string[]
| — | Cc recipient(s) |
bcc | body | string | string[]
| — | Bcc recipient(s) — not shown in headers |
subject | body | string
| — | Subject line, capped at the RFC-5322 line limit. Required for inline sends, forbidden with a template. |
reply_to | body | string | string[]
| — | Reply-To address(es) |
html | body | string
| — | HTML body. Inline sends only — forbidden with a template. |
text | body | string
| — | Plain-text body; auto-derived from html if omitted. Inline sends only. |
headers | body | object
| — | Custom MIME headers, keyed by header name |
tags | body | object[]
| — | Metadata tags attached to the message as `X-Tag-<name>` headers |
template | body | object
| — | Send by reference to a published template |
scheduled_at | body | string (date-time)
| — | ISO-8601 instant to send at; must be in the future and within 30 days. Omit to send now. |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Id of the accepted email — pass it to mail_email_get to follow delivery |
GET/mail/emails/:id
Retrieve an email by id, with its last event
MCP tool: mail_email_get
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Email id — as returned by mail_email_send |
Response
Returns object.
| Field | Type | Always | Description |
|---|
cc | string[]
| • | Cc recipients; empty when there were none |
id | string (uuid)
| • | Email id |
to | string[]
| • | Primary recipients |
bcc | string[]
| • | Bcc recipients; empty when there were none. Never appeared in the message headers. |
from | string
| • | Sender the message was sent as |
status | stringone of: scheduled, queued, sent, failed, canceled, delivered, bounced, complained, suppressed, blocked
| • | Where the email stands: scheduled, queued, sent, failed, canceled, delivered, bounced, complained, suppressed or blocked |
subject | string
| • | Subject line as sent, after any template rendering |
created_at | string
| • | ISO-8601 instant the email was accepted |
last_event | object
| • | The latest lifecycle event, the reason `status` reads as it does |
template_id | string | null
| • | Template the email was rendered from; null for an inline send |
scheduled_at | string | null
| • | ISO-8601 instant the email is scheduled for; null when it was sent immediately |
template_name | string | null
| • | Name of that template; null for an inline send |
provider_message_id | string | null
| • | The sending provider’s own id, for correlating with its logs; null until the email leaves |
PATCH/mail/emails/:id
Reschedule a scheduled email to a new ISO-8601 instant
MCP tool: mail_email_update
Parameters
| Name | In | Type | Required | Description |
|---|
scheduled_at | body | string (date-time)
| • | New ISO-8601 instant to send at; must be in the future and within 30 days |
id | path | string (uuid)
| • | Email id — as returned by mail_email_send |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Id of the accepted email — pass it to mail_email_get to follow delivery |
POST/mail/emails/:id/cancel
Cancel a scheduled email
MCP tool: mail_email_cancel
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Email id — as returned by mail_email_send |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Id of the canceled email |
status | stringone of: canceled
| • | The email’s state after the call — always "canceled" |
POST/mail/emails/batch
Send up to 100 emails in one atomic batch
MCP tool: mail_email_send_batch
Parameters
| Name | In | Type | Required | Description |
|---|
emails | body | object[]
| • | Up to 100 emails to send; `scheduled_at` is not allowed on a batch item |
Response
Returns object[].
| Item field | Type | Always | Description |
|---|
id | string (uuid)
| • | Id of the accepted email |
GET/mail/reputation
Current sender-reputation status for the product: hard-bounce and complaint rates over the rolling window, the sample volume, whether sends are throttled, the tripped metric, and the configured thresholds
MCP tool: mail_reputation_get
Parameters
No parameters.
Response
Returns object.
| Field | Type | Always | Description |
|---|
gated | boolean
| • | True when sending is currently throttled because a rate crossed its threshold |
volume | integer
| • | Emails sent in the window — the denominator of both rates |
complaints | integer
| • | Spam complaints in the window |
thresholds | object
| • | The configured limits the rates above are compared against |
window_days | integer
| • | Length in days of the rolling window the rates below are measured over |
hard_bounces | integer
| • | Hard bounces in the window |
complaint_rate | number
| • | Complaints divided by volume, as a ratio 0-1 (0.001 = 0.1%) |
tripped_metric | string | nullone of: hard_bounce, complaint
| • | Which rate crossed its threshold, or null when nothing did |
hard_bounce_rate | number
| • | Hard bounces divided by volume, as a ratio 0-1 (0.05 = 5%) |
GET/mail/stats
Dashboard aggregation for the product over 7d|30d|90d: sent/delivered/bounced/complained totals, period-over-period deltas, daily volume buckets, and deliverability percentages
MCP tool: mail_stats_get
Parameters
| Name | In | Type | Required | Description |
|---|
period | query | stringone of: 7d, 30d, 90d
| — | Rolling window the aggregation covers, ending now. Defaults to 30d. |
Response
Returns object.
| Field | Type | Always | Description |
|---|
range | object
| • | The absolute instants the period resolved to |
deltas | object
| • | Percent change of each total against the immediately preceding window of the same length |
period | stringone of: 7d, 30d, 90d
| • | The window these numbers cover — the echo of the requested period |
totals | object
| • | Counts over the window |
volume | object[]
| • | One bucket per UTC day in the window, oldest first |
deliverability | object
| • | The three rates senders are judged on, as percentages of sent |
GET/mail/suppressions
List suppressed recipient addresses for the current product (paginated, filter by reason or address substring)
MCP tool: mail_suppression_list
Parameters
| Name | In | Type | Required | Description |
|---|
reason | query | stringone of: hard_bounce, complaint, manual, unsubscribe
| — | Only return entries suppressed for this reason; omit for every reason |
q | query | string
| — | Case-insensitive substring match on the address; omit for no address filter |
cursor | query | string
| — | Opaque pagination cursor from a prior page's next_cursor; omit for the first page |
limit | query | integer
| — | Max entries per page, 1-100 (default 50) |
Response
Returns object.
| Field | Type | Always | Description |
|---|
items | object[]
| • | This page of suppression entries, newest first |
next_cursor | string | null
| • | Opaque cursor to pass back as `cursor` for the next page; null on the last page |
POST/mail/suppressions
Manually suppress a recipient address (reason is always "manual"); idempotent
MCP tool: mail_suppression_add
Parameters
| Name | In | Type | Required | Description |
|---|
address | body | string
| • | Email address to suppress, e.g. "user@example.com"; matched case-insensitively |
note | body | string
| — | Optional free-text note explaining why the address was suppressed |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Suppression entry id |
note | string | null
| • | Free-text note recorded when the entry was added by hand; null otherwise |
reason | stringone of: hard_bounce, complaint, manual, unsubscribe
| • | Why the address is suppressed: hard_bounce and complaint come from SES feedback, unsubscribe from the recipient, manual from mail_suppression_add |
address | string
| • | The suppressed recipient address, lowercased and trimmed |
created_at | string (date-time)
| • | When the address was suppressed (ISO 8601 UTC) |
source_event_id | string (uuid) | null
| • | Id of the email event that caused the suppression; null for a manual entry |
DELETE/mail/suppressions/:address
Remove an address from the suppression list; idempotent (returns whether a row existed)
MCP tool: mail_suppression_remove
Parameters
| Name | In | Type | Required | Description |
|---|
address | path | string
| • | Email address to remove from the suppression list; matched case-insensitively |
Response
Returns object.
| Field | Type | Always | Description |
|---|
address | string
| • | The address the removal was attempted for, as normalized |
removed | boolean
| • | True if an entry was removed; false if the address was not suppressed (the call is idempotent) |
GET/mail/templates
List email templates for the current product; archived ones are hidden unless include_archived is set
MCP tool: mail_template_list
Parameters
| Name | In | Type | Required | Description |
|---|
include_archived | query | boolean
| — | Include archived templates, which are hidden by default. Archiving never stops a send: an archived template is still sendable by its id |
Response
Returns object[].
| Item field | Type | Always | Description |
|---|
id | string (uuid)
| • | Template id |
html | string
| • | HTML body; may contain {{ variable }} placeholders |
name | string
| • | Human label for the template |
text | string | null
| • | Plaintext body; null when none was supplied |
status | stringone of: draft, published
| • | Lifecycle status: published once a revision has gone live |
subject | string
| • | Email subject; may contain {{ variable }} placeholders |
createdAt | string (date-time)
| • | When the template was created (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the template was last modified (ISO 8601 UTC) |
variables | object[]
| • | Declared variables of this template (at most 20) |
archivedAt | string (date-time) | null
| • | When the template was archived (ISO 8601 UTC); null while it is listed normally. Archiving never stops a send |
draftRevision | integer | null
| • | Revision number of the open, unpublished draft; null when there is none |
currentRevision | integer | null
| • | Revision number a send renders; null until the template is first published |
POST/mail/templates
Create a draft email template with typed {{ variable }} placeholders
MCP tool: mail_template_create
Parameters
| Name | In | Type | Required | Description |
|---|
name | body | string
| • | Human label for the template |
subject | body | string
| • | Email subject; may contain {{ variable }} placeholders |
html | body | string
| • | HTML body; may contain {{ variable }} placeholders |
text | body | string
| — | Optional plaintext body; derived from html when omitted |
variables | body | object[]
| — | Declared variables ([{name,type,optional,fallback}], <=20) |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Template id |
html | string
| • | HTML body; may contain {{ variable }} placeholders |
name | string
| • | Human label for the template |
text | string | null
| • | Plaintext body; null when none was supplied |
status | stringone of: draft, published
| • | Lifecycle status: published once a revision has gone live |
subject | string
| • | Email subject; may contain {{ variable }} placeholders |
createdAt | string (date-time)
| • | When the template was created (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the template was last modified (ISO 8601 UTC) |
variables | object[]
| • | Declared variables of this template (at most 20) |
archivedAt | string (date-time) | null
| • | When the template was archived (ISO 8601 UTC); null while it is listed normally. Archiving never stops a send |
draftRevision | integer | null
| • | Revision number of the open, unpublished draft; null when there is none |
currentRevision | integer | null
| • | Revision number a send renders; null until the template is first published |
DELETE/mail/templates/:id
Delete a template
MCP tool: mail_template_delete
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Template id to delete |
Response
Returns object.
| Field | Type | Always | Description |
|---|
deleted | boolean
| • | True once the template is gone |
GET/mail/templates/:id
Get a single email template by id, with its send-usage rollup
MCP tool: mail_template_get
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Template id |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Template id |
html | string
| • | HTML body; may contain {{ variable }} placeholders |
name | string
| • | Human label for the template |
text | string | null
| • | Plaintext body; null when none was supplied |
usage | object
| • | Send-usage rollup for this template |
status | stringone of: draft, published
| • | Lifecycle status: published once a revision has gone live |
subject | string
| • | Email subject; may contain {{ variable }} placeholders |
createdAt | string (date-time)
| • | When the template was created (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the template was last modified (ISO 8601 UTC) |
variables | object[]
| • | Declared variables of this template (at most 20) |
archivedAt | string (date-time) | null
| • | When the template was archived (ISO 8601 UTC); null while it is listed normally. Archiving never stops a send |
draftRevision | integer | null
| • | Revision number of the open, unpublished draft; null when there is none |
currentRevision | integer | null
| • | Revision number a send renders; null until the template is first published |
PATCH/mail/templates/:id
Update a template. The edit lands in its open draft revision; the live body only changes on publish
MCP tool: mail_template_update
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Template id |
name | body | string
| — | New human label; unchanged when omitted |
subject | body | string
| — | New email subject; may contain {{ variable }} placeholders. Unchanged when omitted |
html | body | string
| — | New HTML body; unchanged when omitted |
text | body | string | null
| — | New plaintext body; null clears it and it is re-derived from html. Unchanged when omitted |
variables | body | object[]
| — | Replacement list of declared variables ([{name,type,optional,fallback}], <=20). Unchanged when omitted |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Template id |
html | string
| • | HTML body; may contain {{ variable }} placeholders |
name | string
| • | Human label for the template |
text | string | null
| • | Plaintext body; null when none was supplied |
status | stringone of: draft, published
| • | Lifecycle status: published once a revision has gone live |
subject | string
| • | Email subject; may contain {{ variable }} placeholders |
createdAt | string (date-time)
| • | When the template was created (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the template was last modified (ISO 8601 UTC) |
variables | object[]
| • | Declared variables of this template (at most 20) |
archivedAt | string (date-time) | null
| • | When the template was archived (ISO 8601 UTC); null while it is listed normally. Archiving never stops a send |
draftRevision | integer | null
| • | Revision number of the open, unpublished draft; null when there is none |
currentRevision | integer | null
| • | Revision number a send renders; null until the template is first published |
POST/mail/templates/:id/archive
Hide a template from listings and pickers. Sending by its id keeps working — this is not a delete
MCP tool: mail_template_archive
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Template id to archive |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Template id |
html | string
| • | HTML body; may contain {{ variable }} placeholders |
name | string
| • | Human label for the template |
text | string | null
| • | Plaintext body; null when none was supplied |
status | stringone of: draft, published
| • | Lifecycle status: published once a revision has gone live |
subject | string
| • | Email subject; may contain {{ variable }} placeholders |
createdAt | string (date-time)
| • | When the template was created (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the template was last modified (ISO 8601 UTC) |
variables | object[]
| • | Declared variables of this template (at most 20) |
archivedAt | string (date-time) | null
| • | When the template was archived (ISO 8601 UTC); null while it is listed normally. Archiving never stops a send |
draftRevision | integer | null
| • | Revision number of the open, unpublished draft; null when there is none |
currentRevision | integer | null
| • | Revision number a send renders; null until the template is first published |
DELETE/mail/templates/:id/draft
Throw away the open, unpublished draft of a template. The live revision is untouched
MCP tool: mail_template_draft_discard
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Template id whose open draft is thrown away |
Response
Returns object.
| Field | Type | Always | Description |
|---|
revision | integer
| • | Revision number that was discarded |
discarded | boolean
| • | True once the open draft is gone |
POST/mail/templates/:id/publish
Publish a template: promote its open draft revision to live. No open draft is an idempotent no-op
MCP tool: mail_template_publish
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Template id to publish |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Template id |
html | string
| • | HTML body; may contain {{ variable }} placeholders |
name | string
| • | Human label for the template |
text | string | null
| • | Plaintext body; null when none was supplied |
status | stringone of: draft, published
| • | Lifecycle status: published once a revision has gone live |
subject | string
| • | Email subject; may contain {{ variable }} placeholders |
createdAt | string (date-time)
| • | When the template was created (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the template was last modified (ISO 8601 UTC) |
variables | object[]
| • | Declared variables of this template (at most 20) |
archivedAt | string (date-time) | null
| • | When the template was archived (ISO 8601 UTC); null while it is listed normally. Archiving never stops a send |
draftRevision | integer | null
| • | Revision number of the open, unpublished draft; null when there is none |
currentRevision | integer | null
| • | Revision number a send renders; null until the template is first published |
GET/mail/templates/:id/revisions
List the revisions of a template, oldest first, marking which one is live
MCP tool: mail_template_revision_list
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Template id |
Response
Returns object[].
| Item field | Type | Always | Description |
|---|
html | string
| • | HTML body as authored in this revision |
live | boolean
| • | True for the revision a send currently renders |
text | string | null
| • | Plaintext body as authored in this revision; null when none was supplied |
subject | string
| • | Subject as authored in this revision |
revision | integer
| • | Revision number, counting from 1 for this template |
createdAt | string (date-time)
| • | When this revision was authored (ISO 8601 UTC) |
createdBy | string | null
| • | Identity that authored this revision; null when unknown |
variables | object[]
| • | Variables declared by this revision (at most 20) |
publishedAt | string (date-time) | null
| • | When this revision first went live (ISO 8601 UTC); null for the open draft |
GET/mail/templates/:id/revisions/:revision
Get one revision's content by its number
MCP tool: mail_template_revision_get
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Template id |
revision | path | integer
| • | Revision number, counting from 1 for this template |
Response
Returns object.
| Field | Type | Always | Description |
|---|
html | string
| • | HTML body as authored in this revision |
live | boolean
| • | True for the revision a send currently renders |
text | string | null
| • | Plaintext body as authored in this revision; null when none was supplied |
subject | string
| • | Subject as authored in this revision |
revision | integer
| • | Revision number, counting from 1 for this template |
createdAt | string (date-time)
| • | When this revision was authored (ISO 8601 UTC) |
createdBy | string | null
| • | Identity that authored this revision; null when unknown |
variables | object[]
| • | Variables declared by this revision (at most 20) |
publishedAt | string (date-time) | null
| • | When this revision first went live (ISO 8601 UTC); null for the open draft |
POST/mail/templates/:id/revisions/:revision/restore
Make an earlier revision live again. The pointer moves; content is not copied, so the history keeps its length
MCP tool: mail_template_restore
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Template id |
revision | path | integer
| • | Revision number to make live again |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Template id |
html | string
| • | HTML body; may contain {{ variable }} placeholders |
name | string
| • | Human label for the template |
text | string | null
| • | Plaintext body; null when none was supplied |
status | stringone of: draft, published
| • | Lifecycle status: published once a revision has gone live |
subject | string
| • | Email subject; may contain {{ variable }} placeholders |
createdAt | string (date-time)
| • | When the template was created (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the template was last modified (ISO 8601 UTC) |
variables | object[]
| • | Declared variables of this template (at most 20) |
archivedAt | string (date-time) | null
| • | When the template was archived (ISO 8601 UTC); null while it is listed normally. Archiving never stops a send |
draftRevision | integer | null
| • | Revision number of the open, unpublished draft; null when there is none |
currentRevision | integer | null
| • | Revision number a send renders; null until the template is first published |
POST/mail/templates/:id/unarchive
Return an archived template to listings and pickers
MCP tool: mail_template_unarchive
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Template id to unarchive |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Template id |
html | string
| • | HTML body; may contain {{ variable }} placeholders |
name | string
| • | Human label for the template |
text | string | null
| • | Plaintext body; null when none was supplied |
status | stringone of: draft, published
| • | Lifecycle status: published once a revision has gone live |
subject | string
| • | Email subject; may contain {{ variable }} placeholders |
createdAt | string (date-time)
| • | When the template was created (ISO 8601 UTC) |
updatedAt | string (date-time)
| • | When the template was last modified (ISO 8601 UTC) |
variables | object[]
| • | Declared variables of this template (at most 20) |
archivedAt | string (date-time) | null
| • | When the template was archived (ISO 8601 UTC); null while it is listed normally. Archiving never stops a send |
draftRevision | integer | null
| • | Revision number of the open, unpublished draft; null when there is none |
currentRevision | integer | null
| • | Revision number a send renders; null until the template is first published |
GET/mail/usage
Current free-tier usage for the product: emails sent this day and month with used/limit/remaining, the hard cap, a blocked flag, and the point-in-time contacts count
MCP tool: mail_usage_get
Parameters
No parameters.
Response
Returns object.
| Field | Type | Always | Description |
|---|
emails | object
| • | Email sending usage against the free-tier limits |
period | object
| • | The two windows the counters below are scoped to |
contacts | object
| • | Point-in-time contact storage — a stock, not a per-period flow |
GET/mail/webhooks
List webhook endpoints for the current product (secret omitted).
MCP tool: mail_webhook_list
Parameters
No parameters.
Response
Returns object[].
| Item field | Type | Always | Description |
|---|
id | string (uuid)
| • | Webhook endpoint id |
url | string (uri)
| • | HTTPS URL that signed events are POSTed to |
enabled | boolean
| • | False if delivery is switched off — the endpoint is kept but nothing is sent to it |
created_at | string (date-time)
| • | When the endpoint was registered (ISO 8601 UTC) |
updated_at | string (date-time)
| • | When the endpoint was last changed (ISO 8601 UTC) |
description | string | null
| • | Human label for the endpoint; null if none was given |
enabled_events | string[]one of: email.delivered, email.bounced, email.complained, email.suppressed, email.opened, email.clicked
| • | Event types this endpoint receives; anything else is not delivered to it |
POST/mail/webhooks
Register a webhook endpoint for the current product. Returns the signing secret ONCE.
MCP tool: mail_webhook_create
Parameters
| Name | In | Type | Required | Description |
|---|
url | body | string (uri)
| • | HTTPS URL that signed events are POSTed to; plain http is rejected |
enabled_events | body | string[]one of: email.delivered, email.bounced, email.complained, email.suppressed, email.opened, email.clicked
| • | Event types to deliver; at least one. One or more of: email.delivered, email.bounced, email.complained, email.suppressed, email.opened, email.clicked |
description | body | string
| — | Optional human label for the endpoint, e.g. "billing service" |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Webhook endpoint id |
url | string (uri)
| • | HTTPS URL that signed events are POSTed to |
secret | string
| • | Signing secret for verifying the delivery signature. Returned only when the endpoint is created and never retrievable again — store it now |
enabled | boolean
| • | False if delivery is switched off — the endpoint is kept but nothing is sent to it |
created_at | string (date-time)
| • | When the endpoint was registered (ISO 8601 UTC) |
updated_at | string (date-time)
| • | When the endpoint was last changed (ISO 8601 UTC) |
description | string | null
| • | Human label for the endpoint; null if none was given |
enabled_events | string[]one of: email.delivered, email.bounced, email.complained, email.suppressed, email.opened, email.clicked
| • | Event types this endpoint receives; anything else is not delivered to it |
DELETE/mail/webhooks/:id
Delete a webhook endpoint.
MCP tool: mail_webhook_delete
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Webhook endpoint id; deleting it also discards its delivery history |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Id of the endpoint that was deleted |
deleted | boolean
| • | True once the endpoint and its delivery history are gone |
GET/mail/webhooks/:id
Get a webhook endpoint by id (secret omitted).
MCP tool: mail_webhook_get
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Webhook endpoint id |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Webhook endpoint id |
url | string (uri)
| • | HTTPS URL that signed events are POSTed to |
enabled | boolean
| • | False if delivery is switched off — the endpoint is kept but nothing is sent to it |
created_at | string (date-time)
| • | When the endpoint was registered (ISO 8601 UTC) |
updated_at | string (date-time)
| • | When the endpoint was last changed (ISO 8601 UTC) |
description | string | null
| • | Human label for the endpoint; null if none was given |
enabled_events | string[]one of: email.delivered, email.bounced, email.complained, email.suppressed, email.opened, email.clicked
| • | Event types this endpoint receives; anything else is not delivered to it |
PATCH/mail/webhooks/:id
Update a webhook endpoint (url, enabled_events, description, or enable/disable).
MCP tool: mail_webhook_update
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Webhook endpoint id |
url | body | string (uri)
| — | New HTTPS delivery URL; omit to leave it unchanged |
enabled_events | body | string[]one of: email.delivered, email.bounced, email.complained, email.suppressed, email.opened, email.clicked
| — | Replace the delivered event types; omit to leave them unchanged |
description | body | string | null
| — | New human label, or null to clear it; omit to leave it unchanged |
enabled | body | boolean
| — | Switch delivery on (true) or off (false); omit to leave it unchanged |
Response
Returns object.
| Field | Type | Always | Description |
|---|
id | string (uuid)
| • | Webhook endpoint id |
url | string (uri)
| • | HTTPS URL that signed events are POSTed to |
enabled | boolean
| • | False if delivery is switched off — the endpoint is kept but nothing is sent to it |
created_at | string (date-time)
| • | When the endpoint was registered (ISO 8601 UTC) |
updated_at | string (date-time)
| • | When the endpoint was last changed (ISO 8601 UTC) |
description | string | null
| • | Human label for the endpoint; null if none was given |
enabled_events | string[]one of: email.delivered, email.bounced, email.complained, email.suppressed, email.opened, email.clicked
| • | Event types this endpoint receives; anything else is not delivered to it |
GET/mail/webhooks/:id/deliveries
List recent delivery attempts for a webhook endpoint (status, attempts, last error).
MCP tool: mail_webhook_deliveries_list
Parameters
| Name | In | Type | Required | Description |
|---|
id | path | string (uuid)
| • | Webhook endpoint whose delivery attempts to list |
limit | query | integer
| — | Max delivery attempts to return, 1-100 (default 50) |
Response
Returns object[].
| Item field | Type | Always | Description |
|---|
id | string (uuid)
| • | Delivery attempt id |
status | stringone of: pending, succeeded, failed
| • | Delivery state: pending while attempts remain, succeeded once the endpoint answered 2xx, failed once retries are exhausted |
attempts | integer
| • | How many times delivery has been attempted so far |
event_id | string (uuid)
| • | Id of the email event that was delivered |
created_at | string (date-time)
| • | When the delivery was queued (ISO 8601 UTC) |
event_type | stringone of: email.delivered, email.bounced, email.complained, email.suppressed, email.opened, email.clicked
| • | Type of the delivered event |
last_error | string | null
| • | Error from the last failed attempt; null if the last attempt succeeded or none has run |
updated_at | string (date-time)
| • | When the delivery record was last updated (ISO 8601 UTC) |
endpoint_id | string (uuid)
| • | Id of the webhook endpoint the event was delivered to |
last_attempt_at | string (date-time) | null
| • | When delivery was last attempted (ISO 8601 UTC); null before the first attempt |
response_status | integer | null
| • | HTTP status the endpoint returned on the last attempt; null if it could not be reached |
Was this page helpful?Thanks for your feedback!