Outbound Emails
Outbound email delivery operations.
/outbound-emails
Create an outbound email
Queues a single transactional email for delivery through the sending domain that owns the
from address, and returns it in the queued state. Delivery is asynchronous: track
progress by polling the resource or, preferably, by subscribing to webhooks — the send
advances queued → sent → delivered, or to a terminal bounced, complained,
rejected, suppressed, or failed state.
The send is rejected with 422 when any recipient — to, cc, or bcc — carries an
active all-scope suppression on the domain (bounce, complaint, or manual entry; a
marketing-only unsubscribe does not block transactional sends), and the sending domain
must be active. This endpoint
additionally requires an active subscription; without one it returns 403.
Each recipient (to plus every cc and bcc address) counts as one email against the
plan's included volume. The send's status tracks the primary (to) recipient's delivery
journey; bounces or complaints affecting only cc/bcc recipients are recorded as events
and suppressions without changing the send's status.
Requires the emails:send scope.
Request body
application/vnd.api+json
— CreateOutboundEmailRequestDocument
|
Attribute
|
Type
|
Description
|
|---|---|---|
from
required
|
string | |
to
required
|
string | |
cc
|
string | Optional carbon-copy recipients, visible to everyone on the message. A single address or an array of up to 10 addresses. Duplicate addresses — within the list or repeating `to` — are dropped. Every cc recipient is checked against the domain's `all`-scope suppressions and counts as one email against the plan's included volume. |
bcc
|
string | Optional blind-carbon-copy recipients: they receive the message but never appear in its headers, so other recipients cannot see them. A single address or an array of up to 10 addresses. Duplicate addresses — within the list or repeating `to`/`cc` — are dropped. Every bcc recipient is checked against the domain's `all`-scope suppressions and counts as one email against the plan's included volume. |
reply_to
|
string | Optional reply-to addresses — where replies land instead of the `from` address. A single address or an array of up to 10 addresses. Every address must belong to the sending domain's family: the sending domain itself, a subdomain of it, or a parent of it (for example, sending from `mail.acme.com` allows `support@acme.com`). Addresses outside that family are rejected with a `422`. |
subject
required
|
string | |
html
required
|
string | |
text
|
string|null | |
idempotency_key
|
string|null | |
agent_id
|
string|null | |
track_opens
|
boolean|null | Per-send open-tracking override. Absent or null follows the sending domain's default; false forces tracking off; true requires open tracking enabled on the domain, otherwise 422. |
track_clicks
|
boolean|null | Per-send click-tracking override. Absent or null follows the sending domain's default; false forces tracking off; true requires click tracking enabled on the domain, otherwise 422. |
ai_disclosure
|
boolean|null | Optional AI-provenance marker. Absent or null follows the channel default (off for REST); true attaches the AI-disclosure header to the outgoing message; false forces it off. |
attachments
|
array | Files to attach to the email. Provide the file either inline as base64 with `content`, or as a remote URL with `path` — exactly one per attachment. The total message size, including all attachments after encoding, must stay under 40 MB. Executable and script file types are not permitted. To embed an image inline instead of appending it as a download, set a `content_id` and reference it from the HTML body as `cid:<content_id>` (for example `<img src="cid:logo">`). |
headers
|
object | Optional custom email headers as a name → value map, for example `{"X-Entity-Ref-ID": "ref-123"}` to prevent Gmail from threading related messages. Maximum 10 headers per email. Names are printable ASCII without colons or spaces (max 126 characters); values are printable ASCII without line breaks (max 995 characters); a name and its value combined must not exceed 996 characters. Reserved headers are rejected with a 422 rather than silently dropped: addressing and envelope headers the provider controls (`To`, `From`, `Subject`, `Cc`, `Bcc`, `Reply-To`, `Date`, `Message-ID`, `MIME-Version`, `Content-Type`, `Content-Disposition`, `Return-Path`), headers the platform injects (`Feedback-To`, `X-Complaint-To`, `List-Unsubscribe`, `List-Unsubscribe-Post`, the AI-disclosure header), and any name in the platform's reserved internal-header prefix range (a rejected request names the offending header in its 422 response). To reply to a received email, set `In-Reply-To` to that email's `message_id`, and continue threads by appending prior message ids to `References` (space-separated); both headers are accepted here. A received email's own `In-Reply-To` and `References` are available in its `headers` attribute, so a reply-to-a-reply can build its `References` chain as the parent's `References` plus the parent's `message_id`. Header values must fit the length limit documented above (995 characters) — for very deep threads, trim the OLDEST ids from `References` first, but always keep the first (root) id. No silent truncation happens server-side: an over-length `References` value is rejected by validation. |
curl -X POST https://api.minimailer.app/outbound-emails \ -H "Authorization: Bearer $MINIMAILER_API_TOKEN" \ -H "Accept: application/vnd.api+json" \ -H "Content-Type: application/vnd.api+json" \ -d '{"data":{"type":"outbound-emails","attributes":{"from":"...","to":"...","cc":"...","bcc":"...","reply_to":"...","subject":"...","html":"...","text":"...","idempotency_key":"...","agent_id":"...","track_opens":true,"track_clicks":true,"ai_disclosure":true,"attachments":[],"headers":{}}}}'
Responses
|
Status
|
Description
|
|---|---|
| 201 |
Outbound email created.
OutboundEmailDocument
|
| 401 |
Authentication is required.
ErrorDocument
|
| 403 |
The authenticated token does not have permission to perform this action.
ErrorDocument
|
| 404 |
The referenced sending domain does not exist.
ErrorDocument
|
| 415 |
The request Content-Type must be application/vnd.api+json, with no media type parameters other than profile (ext is rejected — no JSON:API extensions are supported — as is any other parameter such as charset).
ErrorDocument
|
| 409 |
The `idempotency_key` was already used with a different request payload.
ErrorDocument
|
| 422 |
The request document failed validation, including when a recipient carries an active `all`-scope suppression on the domain.
ValidationErrorDocument
|
| 406 |
The Accept header mentions the JSON:API media type only in instances modified by disallowed media type parameters (or only with unsupported ext extensions), so no acceptable representation remains.
ErrorDocument
|
| 429 |
The caller exceeded the API rate limit.
ErrorDocument
|
/outbound-emails
List outbound emails
Returns the authenticated user's outbound emails, newest first. Use the JSON:API filter
parameter to narrow by delivery status and the sort, include, and sparse fields
parameters to shape the response. Requires the emails:read scope.
Parameters
|
Name
|
In
|
Description
|
|---|---|---|
filter
|
query | Exact-match filters, e.g. filter[status]=delivered. Only the fields this endpoint allow-lists are accepted; an unsupported filter returns 400. |
sort
|
query | Comma-separated sort fields; prefix a field with - for descending, e.g. sort=-created_at,name. Defaults to newest-first. Only allow-listed fields are accepted; an unsupported sort returns 400. |
include
|
query | Comma-separated related resources to embed in the response included member (JSON:API compound documents). Example: include=records,webhooks. Nested paths use dot notation, max depth 2. Relationships not declared by the resource, or over-deep paths, return 400. |
fields
|
query | Per-type sparse fieldsets. Example: fields[domains]=name,status restricts the returned attributes for that type. The type must be present in the document and each field must be a known attribute, otherwise 400 is returned. |
page
|
query | Cursor-based pagination, e.g. page[cursor]=eyJpZCI6...&page[size]=50. The cursor is an opaque token issued by the API — take it from the response's links.next / links.prev URLs or meta.next_cursor / meta.prev_cursor; never construct one. size defaults to 25 and is silently capped at 100 (out-of-range or non-numeric values fall back to the default). An invalid or expired cursor falls back to the first page; a cursor replayed with a different sort than it was issued under returns 400; unknown page members such as page[number] return 400. Follow links.next until it is null (or meta.has_more is false) to traverse a collection; links.first restarts traversal. Link URLs carry these parameters URL-encoded (page%5Bcursor%5D=...). |
curl -X GET https://api.minimailer.app/outbound-emails \ -H "Authorization: Bearer $MINIMAILER_API_TOKEN" \ -H "Accept: application/vnd.api+json"
Responses
|
Status
|
Description
|
|---|---|
| 400 |
The include or fields query parameter is not supported (unknown relationship, over-deep include, or unknown sparse-fieldset type or field).
ErrorDocument
|
| 200 |
Outbound emails retrieved.
OutboundEmailCollectionDocument
|
| 401 |
Authentication is required.
ErrorDocument
|
| 403 |
The authenticated token does not have permission to perform this action.
ErrorDocument
|
| 406 |
The Accept header mentions the JSON:API media type only in instances modified by disallowed media type parameters (or only with unsupported ext extensions), so no acceptable representation remains.
ErrorDocument
|
| 429 |
The caller exceeded the API rate limit.
ErrorDocument
|
/outbound-emails/{outboundEmail}
Show an outbound email
Returns a single outbound email owned by the authenticated user, including its current
delivery status and lifecycle timestamps. Poll this to follow a send after it is queued.
Requires the emails:read scope.
Parameters
|
Name
|
In
|
Description
|
|---|---|---|
include
|
query | Comma-separated related resources to embed in the response included member (JSON:API compound documents). Example: include=records,webhooks. Nested paths use dot notation, max depth 2. Relationships not declared by the resource, or over-deep paths, return 400. |
fields
|
query | Per-type sparse fieldsets. Example: fields[domains]=name,status restricts the returned attributes for that type. The type must be present in the document and each field must be a known attribute, otherwise 400 is returned. |
outboundEmail
required
|
path | The outbound email identifier. |
curl -X GET https://api.minimailer.app/outbound-emails/{outboundEmail} \ -H "Authorization: Bearer $MINIMAILER_API_TOKEN" \ -H "Accept: application/vnd.api+json"
Responses
|
Status
|
Description
|
|---|---|
| 400 |
The include or fields query parameter is not supported (unknown relationship, over-deep include, or unknown sparse-fieldset type or field).
ErrorDocument
|
| 200 |
Outbound email retrieved.
OutboundEmailDocument
|
| 401 |
Authentication is required.
ErrorDocument
|
| 403 |
The authenticated token does not have permission to perform this action.
ErrorDocument
|
| 404 |
The requested resource could not be found.
ErrorDocument
|
| 406 |
The Accept header mentions the JSON:API media type only in instances modified by disallowed media type parameters (or only with unsupported ext extensions), so no acceptable representation remains.
ErrorDocument
|
| 429 |
The caller exceeded the API rate limit.
ErrorDocument
|
/outbound-emails/{outboundEmail}
Delete an outbound email
Deletes the record of an outbound email owned by the authenticated user. This removes the
stored message and its metadata; it does not recall a message already handed to the
recipient's mail server. Requires the emails:write scope.
Parameters
|
Name
|
In
|
Description
|
|---|---|---|
outboundEmail
required
|
path | The outbound email identifier. |
curl -X DELETE https://api.minimailer.app/outbound-emails/{outboundEmail} \ -H "Authorization: Bearer $MINIMAILER_API_TOKEN" \ -H "Accept: application/vnd.api+json"
Responses
|
Status
|
Description
|
|---|---|
| 204 | Outbound email deleted. |
| 401 |
Authentication is required.
ErrorDocument
|
| 403 |
The authenticated token does not have permission to perform this action.
ErrorDocument
|
| 404 |
The requested resource could not be found.
ErrorDocument
|
| 406 |
The Accept header mentions the JSON:API media type only in instances modified by disallowed media type parameters (or only with unsupported ext extensions), so no acceptable representation remains.
ErrorDocument
|
| 429 |
The caller exceeded the API rate limit.
ErrorDocument
|
/outbound-emails/{outboundEmail}/stats
Show outbound email stats
Returns aggregate delivery and engagement statistics for a single outbound email — counts
such as deliveries, opens, clicks, bounces, and complaints derived from its tracked events.
Open and click figures are only populated when tracking was enabled for the send. Requires
the emails:read scope.
Parameters
|
Name
|
In
|
Description
|
|---|---|---|
outboundEmail
required
|
path | The outbound email identifier. |
curl -X GET https://api.minimailer.app/outbound-emails/{outboundEmail}/stats \ -H "Authorization: Bearer $MINIMAILER_API_TOKEN" \ -H "Accept: application/vnd.api+json"
Responses
|
Status
|
Description
|
|---|---|
| 200 |
Outbound email statistics retrieved.
OutboundEmailStatsDocument
|
| 401 |
Authentication is required.
ErrorDocument
|
| 403 |
The authenticated token does not have permission to perform this action.
ErrorDocument
|
| 404 |
The requested resource could not be found.
ErrorDocument
|
| 406 |
The Accept header mentions the JSON:API media type only in instances modified by disallowed media type parameters (or only with unsupported ext extensions), so no acceptable representation remains.
ErrorDocument
|
| 429 |
The caller exceeded the API rate limit.
ErrorDocument
|