Skip to content
MiniMailer
Docs
Toggle sidebar
Quick links
Documentation
Knowledge Base
API Reference
Changelog
No results found

Campaigns

Campaign management operations.

POST /campaigns

Create a campaign

Creates a marketing campaign in the draft state for the authenticated user. Set its content — subject, HTML/text body, from address, target audience, schedule, and tracking options — now or via subsequent draft updates. The campaign is not sent on creation; drive it through its lifecycle with PATCH /campaigns/{campaign} (draftscheduled). Requires the campaigns:write scope.

Request body

application/vnd.api+json — CreateCampaignRequestDocument

Attribute
Type
Description
name required string
subject required string Supports merge tags — see `body_html`. Values are inserted literally here, with any carriage return or line feed removed, because the subject becomes a single header line. Must not itself contain a carriage return or line feed; a subject that does is rejected with `422`.
body_html required string Supports merge tags: `{{name}}`, `{{email}}`, `{{unsubscribe_url}}`, `{{unsubscribe_mailto}}`, and any key from a contact's `custom_fields`. Every recipient's message is rendered individually. A tag with no matching value renders as empty. Values are HTML-escaped here and inserted literally in `subject` and `body_text`. The unsubscribe tags are populated only for real audience contacts, never for a `test_mode` send.
body_text string|null Supports merge tags — see `body_html`. Values are inserted literally here.
from_address string|null Optional sender address for the campaign. When set, it must belong to the sending domain's family: the audience's sending domain itself, a subdomain of it, or a parent of it. Addresses outside that family are rejected with a `422`. When null, the campaign sends from `noreply@` on the sending domain.
reply_to string Optional reply-to addresses for the whole campaign — 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, a campaign on `mail.acme.com` allows `support@acme.com`). Addresses outside that family are rejected with a `422`.
test_mode boolean
test_recipient_email string|null
track_opens boolean|null Per-campaign 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-campaign 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.
POST /campaigns
curl -X POST https://api.minimailer.app/campaigns \
  -H "Authorization: Bearer $MINIMAILER_API_TOKEN" \
  -H "Accept: application/vnd.api+json" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{"data":{"type":"campaigns","attributes":{"name":"...","subject":"...","body_html":"...","body_text":"...","from_address":"...","reply_to":"...","test_mode":true,"test_recipient_email":"...","track_opens":true,"track_clicks":true}}}'

Responses

Status
Description
201 Campaign created. CampaignDocument
401 Authentication is required. ErrorDocument
403 The authenticated token does not have permission to perform this action. ErrorDocument
404 The referenced audience 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
422 The request document failed validation. ValidationErrorDocument
409 The request conflicts with the endpoint or current state: the document's resource type does not match the endpoint, its id does not match the resource being updated, or an idempotency key was reused with a different payload. (Creating with a client-generated id and updating relationships on an endpoint that does not support them return 403 instead.) 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
GET /campaigns

List campaigns

Returns the authenticated user's campaigns, newest first, each with its current lifecycle status (draft, scheduled, sending, paused, sent, cancelled, or failed). Supports the JSON:API filter, sort, include, and sparse fields parameters. Requires the campaigns: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=...).
GET /campaigns
curl -X GET https://api.minimailer.app/campaigns \
  -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 Campaigns retrieved. CampaignCollectionDocument
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
GET /campaigns/{campaign}

Show a campaign

Returns a single campaign owned by the authenticated user, including its content, target audience, schedule, and current lifecycle status. Requires the campaigns: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.
campaign required path The campaign identifier.
GET /campaigns/{campaign}
curl -X GET https://api.minimailer.app/campaigns/{campaign} \
  -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 Campaign retrieved. CampaignDocument
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
PATCH /campaigns/{campaign}

Update a campaign

Updates a campaign owned by the authenticated user. This one endpoint does two jobs: editing content and driving the lifecycle state machine.

Content edits (subject, body, from address, schedule, tracking) are allowed only while the campaign is a draft; editing content on any other status returns 422.

Status transitions follow the allowed edges; any other transition returns 422:

  • draftscheduled (queue it to send at its scheduled_at) or cancelled
  • scheduledcancelled
  • sendingpaused
  • pausedsending (resume — re-queues the not-yet-sent recipients) or cancelled

Internal edges (scheduledsending when the schedule fires, sendingsent/failed) happen automatically and are never triggered through this endpoint. Requires the campaigns:write scope.

Parameters

Name
In
Description
campaign required path The campaign identifier.

Request body

application/vnd.api+json — UpdateCampaignRequestDocument

Attribute
Type
Description
status string
name string
subject string Must not contain a carriage return or line feed; a subject that does is rejected with `422`. Merge-tag values are inserted with those characters removed, because the subject becomes a single header line.
body_html string
body_text string|null
from_address string|null Optional sender address for the campaign. When set, it must belong to the sending domain's family: the audience's sending domain itself, a subdomain of it, or a parent of it. Addresses outside that family are rejected with a `422`. When null, the campaign sends from `noreply@` on the sending domain.
reply_to string Optional reply-to addresses for the whole campaign — 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. Addresses outside that family are rejected with a `422`. Editable only while the campaign is a draft.
test_mode boolean
test_recipient_email string|null
scheduled_at string|null
track_opens boolean|null Per-campaign 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-campaign 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.
PATCH /campaigns/{campaign}
curl -X PATCH https://api.minimailer.app/campaigns/{campaign} \
  -H "Authorization: Bearer $MINIMAILER_API_TOKEN" \
  -H "Accept: application/vnd.api+json" \
  -H "Content-Type: application/vnd.api+json" \
  -d '{"data":{"type":"campaigns","attributes":{"status":"...","name":"...","subject":"...","body_html":"...","body_text":"...","from_address":"...","reply_to":"...","test_mode":true,"test_recipient_email":"...","scheduled_at":"...","track_opens":true,"track_clicks":true}}}'

Responses

Status
Description
200 Campaign updated. CampaignDocument
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
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
422 The request document failed validation. ValidationErrorDocument
409 The request conflicts with the endpoint or current state: the document's resource type does not match the endpoint, its id does not match the resource being updated, or an idempotency key was reused with a different payload. (Creating with a client-generated id and updating relationships on an endpoint that does not support them return 403 instead.) 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
DELETE /campaigns/{campaign}

Delete a campaign

Deletes a campaign owned by the authenticated user. To stop an in-flight send, transition it to cancelled via PATCH rather than deleting it. Statistics for a campaign that has already sent are retained on its send records. Requires the campaigns:write scope.

Parameters

Name
In
Description
campaign required path The campaign identifier.
DELETE /campaigns/{campaign}
curl -X DELETE https://api.minimailer.app/campaigns/{campaign} \
  -H "Authorization: Bearer $MINIMAILER_API_TOKEN" \
  -H "Accept: application/vnd.api+json"

Responses

Status
Description
204 Campaign 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
GET /campaigns/{campaign}/stats

Show campaign stats

Returns aggregate delivery and engagement statistics for a campaign — totals such as recipients, deliveries, opens, clicks, bounces, complaints, and unsubscribes derived from its send events. Open and click figures reflect only the tracking that was enabled for the campaign. Figures are most meaningful once the campaign has reached sending or sent. Requires the campaigns:read scope.

Parameters

Name
In
Description
campaign required path The campaign identifier.
GET /campaigns/{campaign}/stats
curl -X GET https://api.minimailer.app/campaigns/{campaign}/stats \
  -H "Authorization: Bearer $MINIMAILER_API_TOKEN" \
  -H "Accept: application/vnd.api+json"

Responses

Status
Description
200 Campaign statistics retrieved. CampaignStatsDocument
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