Reference

API reference

Base URL http://localhost:3000/api/v1. Bodies are JSON; GET and DELETE take their parameters in the query string. Each endpoint is also the MCP tool named under it. The same reference as OpenAPI 3.1.

Audience v2 uses one Subscriber profile with a separate subscription and consent for each newsletter. Use the Subscribers actions for profiles; a legacy contact ID identifies a newsletter subscription, and legacy recipient reads apply only to v1 accounts. On v2, groups require a newsletter parent and cannot grant consent. The current CSV preview is read-only; the existing CSV import is separate from the later durable importer and MailerLite Classic migration.

Campaigns

Drafts, test emails, scheduling, sending, sending in steps and reports.

List countdown campaigns

GET/api/v1/native-campaigns

Lists owned published Apresly campaigns for native email countdown blocks. No recipient is registered.

MCP toollist_native_campaignsKeycontent:readRead-onlySafe to repeatReaches outside ApresMail
Request
curl "http://localhost:3000/api/v1/native-campaigns" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Validate a countdown destination

POST/api/v1/native-campaigns/validate

Checks an owned campaign and optional published checkout destination without registering a recipient.

MCP toolvalidate_native_countdownKeycontent:readRead-onlySafe to repeatReaches outside ApresMail
Parameter
capabilityrequired

body · string

Owned campaign capability returned by list_native_campaigns

checkoutPublicIdrequired

body · string | null

Published Commerce checkout UUID, or null for an image without a link

Request
curl -X POST "http://localhost:3000/api/v1/native-campaigns/validate" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"capability":"…","checkoutPublicId":"…"}'

List campaigns

GET/api/v1/campaigns

Lists campaigns, newest activity first: sent issues by send date, scheduled ones by send time, drafts by last edit. Email content is left out; get_campaign has it. Filter channel sms to list pilot campaigns without an email plan.

MCP toollist_campaignsKeycontent:readRead-onlySafe to repeat
Parameter
newsletter

query · string

Only this newsletter's: its ID or slug. Default: every newsletter.

channel

query · "email" | "sms"

Filter by channel; channel sms is available without an email plan

status

query · "draft" | "scheduled" | "sending" | "paused" | "sent"

Only campaigns with this status

limit

query · integer

How many, 50 by default, 200 at most

Request
curl "http://localhost:3000/api/v1/campaigns?status=sent&limit=10" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Get a campaign

GET/api/v1/campaigns/{id}

Gets a campaign with its content, stats and, for drafts, what would block sending it now.

MCP toolget_campaignKeycontent:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The campaign's ID

Request
curl "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Get a campaign's report

GET/api/v1/campaigns/{id}/report

Delivery, open, click, bounce, complaint and unsubscribe rates of a sent campaign, its list cleanup emails, results by inbox provider, and remaining contacts. SMS returns delivery status counts and reserved, committed and released USD caps without email engagement metrics.

MCP toolget_campaign_reportKeycontent:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The campaign's ID

Request
curl "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/report" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Create a draft campaign

POST/api/v1/campaigns

Creates an email draft by default, or an SMS draft with channel sms, name, sms.senderId, sms.template and a stable requestId. SMS rejects email content, archive and segments; at most 100 newsletter groups. Prepare and approve a review before sending.

MCP toolcreate_campaignKeycontent:write
Parameter
channel

body · "email" | "sms"

Campaign channel; omitted means email. SMS uses name, sms and requestId instead of email content.

name

body · string

Private SMS campaign name, at most 200 characters

sms

body · object

SMS sender and plain text; only {{first_name}} personalization is supported

sms.senderIdrequired

body · string

sms.templaterequired

body · string

requestId

body · string

Required for SMS: stable UUID reused with identical input after a timeout

newsletter

body · string

The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest.

groupIds

body · string[]

SMS: union of up to 100 newsletter groups; empty selects the newsletter

subject

body · string

Subject line, 200 characters at most

previewText

body · string

Text inbox apps show after the subject, 300 characters at most

format

body · "markdown" | "rich" | "html"

markdown (the default when content is given), rich or html, as in update_campaign

content

body · string

The body in that format, 500 KB at most

archiveSlug

body · string

The issue's page path once sent. Default: made from the subject; a taken slug gets a number.

segment

body · string | null

A segment's ID (list_segments): only the active contacts it picks when the campaign goes out get it. null: every active contact.

audienceRules

body · object | null

Additional campaign-specific OR sets of AND conditions; null removes these rules. Ready v2 email audiences only.

Request
curl -X POST "http://localhost:3000/api/v1/campaigns" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"subject":"This week","previewText":"Three links worth your time","content":"# This week\n\nThree links worth your time."}'

Update a draft campaign

PATCH/api/v1/campaigns/{id}

Changes an unapproved draft using its expectedRevision. Content, segment and organizational group selection share one revision. Stale edits conflict without overwriting text. Scheduled or approved campaigns cannot be edited.

MCP toolupdate_campaignKeycontent:writeSafe to repeat
Parameter
channel

body · "email" | "sms"

Campaign channel; omitted means email. SMS uses name, sms and requestId instead of email content.

name

body · string

Private SMS campaign name, at most 200 characters

sms

body · object

SMS sender and plain text; only {{first_name}} personalization is supported

sms.senderIdrequired

body · string

sms.templaterequired

body · string

requestId

body · string

Required for SMS: stable UUID reused with identical input after a timeout

idrequired

path · string

The campaign's ID

expectedRevisionrequired

body · integer

The revision last read by this editor; stale edits return conflict

groupIds

body · string[]

SMS: union of up to 100 newsletter groups; empty selects the newsletter

audienceLimit

body · integer | null

Maximum reviewed recipients, 1 to 25000; null restores the default maximum of 25000

subject

body · string

Subject line, 200 characters at most

previewText

body · string

Text inbox apps show after the subject, 300 characters at most

format

body · "markdown" | "rich" | "html"

With content: the format it's in. Default: the campaign's current format.

content

body · string

The body in that format, 500 KB at most

segment

body · string | null

A segment's ID (list_segments): only the active contacts it picks when the campaign goes out get it. null: every active contact.

audienceRules

body · object | null

Additional campaign-specific OR sets of AND conditions; null removes these rules. Ready v2 email audiences only.

Request
curl -X PATCH "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"expectedRevision":"…","subject":"This week, and one more link"}'

Delete a draft campaign

DELETE/api/v1/campaigns/{id}

Deletes a draft or scheduled campaign: it leaves every list and a scheduled send never goes out. Sent campaigns can't be deleted.

MCP tooldelete_campaignKeycontent:writeCan't be undoneSafe to repeat
Parameter
idrequired

path · string

The campaign's ID

Request
curl -X DELETE "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Duplicate a campaign

POST/api/v1/campaigns/{id}/duplicate

Copies a campaign's subject, preview text and content into a new draft.

MCP toolduplicate_campaignKeycontent:write
Parameter
idrequired

path · string

The campaign's ID

Request
curl -X POST "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/duplicate" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Send a test email

POST/api/v1/campaigns/{id}/test

Sends the saved campaign to the specified test address, or the signed-in user/account owner when omitted, with [Test] in the subject. It counts toward the account's email allowance.

MCP toolsend_test_emailKeymessages:sendReaches outside ApresMail
Parameter
idrequired

path · string

The campaign's ID

to

body · string

The test email destination; omitted uses the signed-in user or account owner

Request
curl -X POST "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/test" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Schedule a reviewed campaign

POST/api/v1/campaigns/{id}/schedule

Approves a retained review for a future schedule. Sending can't be undone: messages can't be recalled once they go out. Ask the user to confirm first. Requires review ID, revision, digest and stable request UUID; no live audience is selected here.

MCP toolschedule_campaignKeymessages:sendCan't be undoneSafe to repeatReaches outside ApresMail
Parameter
idrequired

path · string

The campaign's ID

expectedCapMicrousd

body · string

SMS only: exact maximum micro-USD cost returned by the ready review

reviewId

body · string

Retained ready review ID belonging to this campaign

expectedRevision

body · integer

Draft revision captured by this review

snapshotDigest

body · string

Exact snapshot digest returned by the ready review

requestId

body · string

Stable approval UUID; reuse the same value and input after a timeout

validityHours

body · integer

Execution validity after its due time, 1 to 72 hours; default 24

audienceLimit

body · integer

Maximum contacts to include in this preview

segment

body · string | null

A segment's ID (list_segments): only the active contacts it picks when the campaign goes out get it. null: every active contact.

scheduledAt

body · string

Scheduled ISO instant

timezone

body · string

IANA timezone

localDateTime

body · string

Local wall-clock time

Request
curl -X POST "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/schedule" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Cancel a reviewed schedule

POST/api/v1/campaigns/{id}/unschedule

Changes only the specified approved execution. Requires its current lifecycle revision and a stable request UUID. Unknown deliveries are never retried.

MCP toolunschedule_campaignKeycontent:writeSafe to repeat
Parameter
idrequired

path · string

The campaign's ID

reviewIdrequired

body · string

The review's ID

requestIdrequired

body · string

Stable UUID for this lifecycle request; reuse after a timeout

expectedLifecycleRevisionrequired

body · integer

Lifecycle revision returned by the latest review read

expectedUnknownGeneration

body · integer

Unknown-outcome generation explicitly acknowledged on resume; zero for a clean execution

Request
curl -X POST "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/unschedule" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reviewId":"…","requestId":"…","expectedLifecycleRevision":"…"}'

Send a reviewed campaign now

POST/api/v1/campaigns/{id}/send

Approves exactly the retained review for sending now. Sending can't be undone: messages can't be recalled once they go out. Ask the user to confirm first. Requires review ID, revision, digest and stable request UUID; no live audience is selected here.

MCP toolsend_campaignKeymessages:sendCan't be undoneSafe to repeatReaches outside ApresMail
Parameter
idrequired

path · string

The campaign's ID

expectedCapMicrousd

body · string

SMS only: exact maximum micro-USD cost returned by the ready review

reviewId

body · string

Retained ready review ID belonging to this campaign

expectedRevision

body · integer

Draft revision captured by this review

snapshotDigest

body · string

Exact snapshot digest returned by the ready review

requestId

body · string

Stable approval UUID; reuse the same value and input after a timeout

validityHours

body · integer

Execution validity after its due time, 1 to 72 hours; default 24

audienceLimit

body · integer

Maximum contacts to include in this preview

segment

body · string | null

A segment's ID (list_segments): only the active contacts it picks when the campaign goes out get it. null: every active contact.

Request
curl -X POST "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/send" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Send a campaign to more contacts

POST/api/v1/campaigns/{id}/send-more

Disabled: duplicate the campaign and prepare a new review for another intentional send. Sending can't be undone: messages can't be recalled once they go out. Ask the user to confirm first.

MCP toolsend_campaign_to_moreKeymessages:sendCan't be undoneReaches outside ApresMail
Parameter
idrequired

path · string

The campaign's ID

additional

body · integer

Legacy input; this operation always conflicts

Request
curl -X POST "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/send-more" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Pause a reviewed campaign

POST/api/v1/campaigns/{id}/pause

Changes only the specified approved execution. Requires its current lifecycle revision and a stable request UUID. Unknown deliveries are never retried.

MCP toolpause_campaignKeycontent:writeSafe to repeat
Parameter
idrequired

path · string

The campaign's ID

reviewIdrequired

body · string

The review's ID

requestIdrequired

body · string

Stable UUID for this lifecycle request; reuse after a timeout

expectedLifecycleRevisionrequired

body · integer

Lifecycle revision returned by the latest review read

expectedUnknownGeneration

body · integer

Unknown-outcome generation explicitly acknowledged on resume; zero for a clean execution

Request
curl -X POST "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/pause" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reviewId":"…","requestId":"…","expectedLifecycleRevision":"…"}'

Resume a reviewed campaign

POST/api/v1/campaigns/{id}/resume

Changes only the specified approved execution. Sending can't be undone: messages can't be recalled once they go out. Ask the user to confirm first. Requires its current lifecycle revision and a stable request UUID. Unknown deliveries are never retried.

MCP toolresume_campaignKeymessages:sendCan't be undoneSafe to repeatReaches outside ApresMail
Parameter
idrequired

path · string

The campaign's ID

reviewIdrequired

body · string

The review's ID

requestIdrequired

body · string

Stable UUID for this lifecycle request; reuse after a timeout

expectedLifecycleRevisionrequired

body · integer

Lifecycle revision returned by the latest review read

expectedUnknownGeneration

body · integer

Unknown-outcome generation explicitly acknowledged on resume; zero for a clean execution

Request
curl -X POST "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/resume" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reviewId":"…","requestId":"…","expectedLifecycleRevision":"…"}'

Cancel an approved campaign

POST/api/v1/campaigns/{id}/cancel

Permanently cancels this approved execution and suppresses unstarted queued/held work in bounded batches. Provider-started and unknown deliveries remain unchanged.

MCP toolcancel_campaignKeycontent:writeCan't be undoneSafe to repeat
Parameter
idrequired

path · string

The campaign's ID

reviewIdrequired

body · string

The review's ID

requestIdrequired

body · string

Stable UUID for this lifecycle request; reuse after a timeout

expectedLifecycleRevisionrequired

body · integer

Lifecycle revision returned by the latest review read

expectedUnknownGeneration

body · integer

Unknown-outcome generation explicitly acknowledged on resume; zero for a clean execution

Request
curl -X POST "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/cancel" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reviewId":"…","requestId":"…","expectedLifecycleRevision":"…"}'

Update a campaign's archive page

PATCH/api/v1/campaigns/{id}/archive

Changes the path of a campaign's archive page (/p/<slug>), or pins a sent issue to the top of the archive. Works on sent campaigns too.

MCP toolupdate_campaign_archiveKeysettings:manageSafe to repeat
Parameter
idrequired

path · string

The campaign's ID

expectedRevision

body · integer

Required when changing the archive slug; the revision last read by this editor

slug

body · string

Lowercase letters, digits and dashes. Empty removes it from a draft.

pinned

body · boolean

Pinned issues lead the archive

Request
curl -X PATCH "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/archive" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"pinned":true}'

Preview the list cleanup of a send

GET/api/v1/campaigns/{id}/cleanup-preview

Counts what the newsletter's list cleanup would do if the campaign went out now: issues sent, last-chance emails instead, contacts still waiting to answer one, and contacts made dormant. Reads the whole list, so it can take a few seconds.

MCP toolpreview_campaign_cleanupKeycontent:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The campaign's ID

audienceLimit

query · integer

Count for a send capped at this many contacts

includeRanks

query · boolean

Also return, for each cold contact, how many issue recipients come before it, to recount any limit without asking again

Request
curl "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/cleanup-preview" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Preview campaign audience

GET/api/v1/campaigns/{id}/audience-preview

Counts current eligible recipients in a saved v2 email draft using its groups, segment and additional conditions. The dashboard can preview validated unsaved selection changes without writing them. Read-only; no review, schedule or email is created. Counts are a live observation and can change before sending.

MCP toolpreview_campaign_audienceKeycontent:read + audience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The campaign's ID

expectedRevisionrequired

query · integer

The revision last read by this editor; stale edits return conflict

Request
curl "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/audience-preview" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Prepare a campaign review

POST/api/v1/campaigns/{id}/reviews

Freezes this draft's content and audience selection for a bounded background review. Does not approve or send messages. The same request ID and input returns its original review, including a terminal result; different input conflicts.

MCP toolprepare_campaign_reviewKeycontent:writeSafe to repeat
Parameter
idrequired

path · string

Campaign ID in this account

expectedRevisionrequired

body · integer

Draft revision that the operator reviewed

requestIdrequired

body · string

Stable UUID for this preparation request; reuse it after a timeout

Request
curl -X POST "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/reviews" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"expectedRevision":"…","requestId":"…"}'

Get a campaign review

GET/api/v1/campaigns/{id}/reviews/{reviewId}

Reads an explicit summary of retained campaign review content, selection, counters and lifecycle. Preparation diagnostics may be stale and do not grant permission to send. Historical reads remain available while review preparation is disabled.

MCP toolget_campaign_reviewKeycontent:readRead-onlySafe to repeat
Parameter
idrequired

path · string

Campaign ID in this account

reviewIdrequired

path · string

Review ID belonging to this campaign and account

Request
curl "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/reviews/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

List campaign review recipients

GET/api/v1/campaigns/{id}/reviews/{reviewId}/recipients

Reads a bounded retained audience snapshot, not current sending permission. Building reviews conflict. Erased or missing canonical recipients are omitted immediately; an empty page may still have nextCursor. Historical reads remain available while preparation is disabled.

MCP toollist_campaign_review_recipientsKeyaudience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

Campaign ID in this account

reviewIdrequired

path · string

Review ID belonging to this campaign and account

cursor

query · string

Previous page nextCursor for this exact review

limit

query · integer

Raw snapshot rows per page, 1 to 100; defaults to 50

Request
curl "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/reviews/6650f1c2e9b1d4a012345678/recipients" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Preview frozen campaign content

GET/api/v1/campaigns/{id}/reviews/{reviewId}/preview

Reads the retained email preview or a synthetic SMS example including its complete unsubscribe-link length. Links are disabled and no tracking or unsubscribe credentials are generated. Never renders mutable newsletter defaults.

MCP toolget_campaign_review_previewKeycontent:readRead-onlySafe to repeat
Parameter
idrequired

path · string

Campaign ID in this account

reviewIdrequired

path · string

Review ID belonging to this campaign and account

Request
curl "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/reviews/6650f1c2e9b1d4a012345678/preview" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Approve a campaign review

POST/api/v1/campaigns/{id}/reviews/{reviewId}/approve

Approves exactly the retained content and audience snapshot. Sending can't be undone. Reuse the same request UUID and input after a timeout; changed input conflicts.

MCP toolapprove_campaign_reviewKeymessages:sendCan't be undoneSafe to repeatReaches outside ApresMail
Parameter
expectedCapMicrousd

body · string

SMS only: exact maximum micro-USD cost returned by the ready review

reviewIdrequired

path · string

Retained ready review ID belonging to this campaign

expectedRevisionrequired

body · integer

Draft revision captured by this review

snapshotDigestrequired

body · string

Exact snapshot digest returned by the ready review

requestIdrequired

body · string

Stable approval UUID; reuse the same value and input after a timeout

validityHours

body · integer

Execution validity after its due time, 1 to 72 hours; default 24

moderequired

body · "now" | "scheduled"

Send now or approve a future schedule

scheduledAt

body · string

Scheduled ISO instant; required only for scheduled mode

timezone

body · string

IANA timezone of the schedule

localDateTime

body · string

Local wall-clock time represented by scheduledAt

idrequired

path · string

Campaign ID in this account

Request
curl -X POST "http://localhost:3000/api/v1/campaigns/6650f1c2e9b1d4a012345678/reviews/6650f1c2e9b1d4a012345678/approve" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"expectedRevision":"…","snapshotDigest":"…","requestId":"…","mode":"…"}'

Overview

Subscribers, email results and sends per hour, as on the dashboard's first page.

Get the overview

GET/api/v1/overview

The dashboard's overview for one newsletter: subscribers each day of the last 30 days, email results of the last 30 days against the 30 before, emails sent per hour today and yesterday, and the plan's usage this month, which the account's newsletters share.

MCP toolget_overviewKeycontent:readRead-onlySafe to repeat
Parameter
newsletter

query · string

The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest.

timeZone

query · string

IANA time zone for days and hours, e.g. Europe/Paris. Default: UTC.

Request
curl "http://localhost:3000/api/v1/overview?timeZone=Europe%2FParis" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Newsletters

Sender, postal address, welcome and confirmation emails, list cleanup, archive and theme.

List newsletters

GET/api/v1/newsletters

Lists the account's newsletters, 3 at most, first created first, with their settings and active contacts. Actions that take a newsletter use the first one when it's left out.

MCP toollist_newslettersKeycontent:readRead-onlySafe to repeat
Request
curl "http://localhost:3000/api/v1/newsletters" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Get a newsletter

GET/api/v1/newsletters/{id}

Gets a newsletter's settings: sender, postal address, welcome and confirmation emails, list cleanup, archive and theme.

MCP toolget_newsletterKeycontent:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The newsletter's ID or slug

Request
curl "http://localhost:3000/api/v1/newsletters/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Create a newsletter

POST/api/v1/newsletters

Creates a newsletter. An account has up to 3, sharing its account's assigned email and subscriber limits; one more answers conflict. Without a fromEmail it sends from the shared address hello@<slug>.<shared domain>, which ApresMail sets up in a few minutes. List cleanup is on unless cleanup.enabled is false. Without a postalAddress, its emails print the server's default if it has one: the administrator-configured address.

MCP toolcreate_newsletterKeysettings:manage + messages:send
Parameter
namerequired

body · string

The newsletter's name, shown in emails and on the archive

slug

body · string

Lowercase letters, digits and dashes. Default: made from the name, numbered when another newsletter has it.

imageUrl

body · string

Square logo, 128×128 or larger: an https:// link

fromName

body · string

Name in the From field

fromEmail

body · string

The shared address (hello@<slug>.<shared domain>, set automatically) or an address on a domain added to this account

replyTo

body · string

Where replies go. Empty: replies to the shared address go to the account owner.

postalAddress

body · string

Printed in the footer of every email. Never set, it uses the configured default; saved empty, there is none and sending waits for one.

archiveEnabled

body · boolean

A public page for each sent issue, with a signup form. On for new newsletters: the website goes live after the first issue.

description

body · string

One sentence under the name on the archive, 200 characters at most

author

body · object

The archive's author page; the author's name is fromName

author.bio

body · string

Under the author's name on the archive, 160 characters at most

author.imageUrl

body · string

Author photo: an https:// link. The newsletter image otherwise.

socialLinks

body · string[]

https:// links shown on the archive, 8 at most

requireConfirmation

body · boolean

Confirmed opt-in: new signups get an email with a button and only join once they click it. On for new newsletters. New subscribers get the confirmation email or the welcome email: turning it on while the welcome email is on needs welcome.enabled false in the same request.

cleanup

body · object

List cleanup at each send: contacts who ignored several issues get a last-chance email instead, and become dormant if they don't answer

cleanup.enabled

body · boolean

On for new newsletters

cleanup.issues

body · number | null

Ignored issues in a row before the last-chance email, 2 to 100. Default 6.

cleanup.days

body · number | null

Days without an open, click or signup, 30 to 3650. Default 180.

welcome

body · object

Email sent to each new subscriber, while signups don't need confirming: turning it on while requireConfirmation is on needs requireConfirmation false in the same request.

welcome.enabled

body · boolean

welcome.subject

body · string

welcome.previewText

body · string

welcome.markdown

body · string

Markdown

confirmation

body · object

The confirmation email for confirmed opt-in. Sent back unchanged, the built-in one stays built-in and follows the name and description.

confirmation.subject

body · string

confirmation.previewText

body · string

confirmation.markdown

body · string

Markdown that keeps the button: an HTML link like <a href="{{confirm_url}}">Confirm</a>

theme

body · object

Its look on its website and in its emails: a preset from list_themes and what's changed on top of it. Send only what changes; null takes a choice back to the preset's.

theme.preset

body · "mailcheap" | "broadsheet" | "garden" | "midnight" | "poster" | "swiss" | "typewriter" | "sunset"

A preset from list_themes. Another preset starts over from it: the changes made to the one before go, unless this call sends new ones.

theme.colors

body · object | null

Hex colors. null takes one back to the preset's; the other shades derive from these three.

theme.fonts

body · object | null

Fonts from list_themes. Mail clients without web fonts, like Gmail, show a close system font.

theme.headingWeight

body · integer | null

Fonts with fewer weights use their closest

theme.radius

body · string | null

Corners of buttons, cards and pictures

theme.shadow

body · string | null

Cards and forms on the website. Emails have none.

theme.spacing

body · string | null

Line height and space between paragraphs

Request
curl -X POST "http://localhost:3000/api/v1/newsletters" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Field notes","postalAddress":"Field Notes Ltd, 1 Main St, Paris, France"}'

Update a newsletter

PATCH/api/v1/newsletters/{id}

Changes a newsletter's settings. Send only the fields to change; nested groups (welcome, confirmation, cleanup, author) keep the fields you leave out. An account changes slugs 3 times a day at most: one more answers rate_limited.

MCP toolupdate_newsletterKeysettings:manage + messages:sendSafe to repeat
Parameter
idrequired

path · string

The newsletter's ID or slug

name

body · string

The newsletter's name, shown in emails and on the archive

slug

body · string

Lowercase letters, digits and dashes, not a name ApresMail keeps like www, api or mail. The shared from address (hello@<slug>.<shared domain>) and the archive subdomain follow it.

imageUrl

body · string

Square logo, 128×128 or larger: an https:// link

fromName

body · string

Name in the From field

fromEmail

body · string

The shared address (hello@<slug>.<shared domain>, set automatically) or an address on a domain added to this account

replyTo

body · string

Where replies go. Empty: replies to the shared address go to the account owner.

postalAddress

body · string

Printed in the footer of every email. Never set, it uses the configured default; saved empty, there is none and sending waits for one.

archiveEnabled

body · boolean

A public page for each sent issue, with a signup form. On for new newsletters: the website goes live after the first issue.

description

body · string

One sentence under the name on the archive, 200 characters at most

author

body · object

The archive's author page; the author's name is fromName

author.bio

body · string

Under the author's name on the archive, 160 characters at most

author.imageUrl

body · string

Author photo: an https:// link. The newsletter image otherwise.

socialLinks

body · string[]

https:// links shown on the archive, 8 at most

requireConfirmation

body · boolean

Confirmed opt-in: new signups get an email with a button and only join once they click it. On for new newsletters. New subscribers get the confirmation email or the welcome email: turning it on while the welcome email is on needs welcome.enabled false in the same request.

cleanup

body · object

List cleanup at each send: contacts who ignored several issues get a last-chance email instead, and become dormant if they don't answer

cleanup.enabled

body · boolean

On for new newsletters

cleanup.issues

body · number | null

Ignored issues in a row before the last-chance email, 2 to 100. Default 6.

cleanup.days

body · number | null

Days without an open, click or signup, 30 to 3650. Default 180.

welcome

body · object

Email sent to each new subscriber, while signups don't need confirming: turning it on while requireConfirmation is on needs requireConfirmation false in the same request.

welcome.enabled

body · boolean

welcome.subject

body · string

welcome.previewText

body · string

welcome.markdown

body · string

Markdown

confirmation

body · object

The confirmation email for confirmed opt-in. Sent back unchanged, the built-in one stays built-in and follows the name and description.

confirmation.subject

body · string

confirmation.previewText

body · string

confirmation.markdown

body · string

Markdown that keeps the button: an HTML link like <a href="{{confirm_url}}">Confirm</a>

theme

body · object

Its look on its website and in its emails: a preset from list_themes and what's changed on top of it. Send only what changes; null takes a choice back to the preset's.

theme.preset

body · "mailcheap" | "broadsheet" | "garden" | "midnight" | "poster" | "swiss" | "typewriter" | "sunset"

A preset from list_themes. Another preset starts over from it: the changes made to the one before go, unless this call sends new ones.

theme.colors

body · object | null

Hex colors. null takes one back to the preset's; the other shades derive from these three.

theme.fonts

body · object | null

Fonts from list_themes. Mail clients without web fonts, like Gmail, show a close system font.

theme.headingWeight

body · integer | null

Fonts with fewer weights use their closest

theme.radius

body · string | null

Corners of buttons, cards and pictures

theme.shadow

body · string | null

Cards and forms on the website. Emails have none.

theme.spacing

body · string | null

Line height and space between paragraphs

Request
curl -X PATCH "http://localhost:3000/api/v1/newsletters/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"replyTo":"jane@example.com","requireConfirmation":true}'

List themes

GET/api/v1/themes

Lists the theme presets a newsletter can take, with their colors, fonts and choices, and the options to change them with: fonts, heading weights, radius, shadow and spacing. update_newsletter's theme sets them.

MCP toollist_themesKeycontent:readRead-onlySafe to repeat
Request
curl "http://localhost:3000/api/v1/themes" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Check a slug

GET/api/v1/newsletters/slugs/{slug}

Says whether a newsletter can take a slug: available, or taken by another newsletter, reserved by ApresMail or invalid, with the message saving it would answer. Checking doesn't count toward the 3 slug changes a day.

MCP toolcheck_newsletter_slugKeycontent:readRead-onlySafe to repeat
Parameter
slugrequired

path · string

The slug to check

id

query · string

The newsletter that would take it, by ID or slug: its own slug is available to it

Request
curl "http://localhost:3000/api/v1/newsletters/slugs/6650f1c2e9b1d4a012345678?slug=field-notes" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Send a test of the welcome email

POST/api/v1/newsletters/{id}/welcome-test

Sends the saved welcome email to the account owner's address, switched on or not. It counts toward the plan's emails.

MCP toolsend_welcome_test_emailKeymessages:sendReaches outside ApresMail
Parameter
idrequired

path · string

The newsletter's ID or slug

Request
curl -X POST "http://localhost:3000/api/v1/newsletters/6650f1c2e9b1d4a012345678/welcome-test" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

SMS

Get SMS settings

GET/api/v1/sms/settings

Shows the account's controlled SMS pilot limit. This is a spending cap, not a bill or retail price.

MCP toolget_sms_settingsKeycontent:readRead-onlySafe to repeat
Request
curl "http://localhost:3000/api/v1/sms/settings" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

List SMS senders

GET/api/v1/sms/senders

Lists this account's approved or pending brand senders without AWS resource details.

MCP toollist_sms_sendersKeycontent:readRead-onlySafe to repeat
Parameter
cursor

query · string

The resource ID in this account

limit

query · integer

Number of senders per page, up to 100

Request
curl "http://localhost:3000/api/v1/sms/senders" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Get subscriber SMS preferences

GET/api/v1/subscribers/{id}/sms

Shows a masked verified phone and independent SMS preferences; never exposes a full phone number.

MCP toolget_subscriber_smsKeyaudience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The resource ID in this account

Request
curl "http://localhost:3000/api/v1/subscribers/6650f1c2e9b1d4a012345678/sms" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Remove subscriber SMS phone

DELETE/api/v1/subscribers/{id}/sms/phone

Removes the phone and withdraws all its SMS consents. Email subscriptions remain unchanged.

MCP toolremove_subscriber_sms_phoneKeyaudience:write + audience:readCan't be undoneSafe to repeat
Parameter
idrequired

path · string

The resource ID in this account

expectedPhoneVersionrequired

query · integer

The current version; stale changes are rejected

requestIdrequired

query · string

A unique request ID; reuse unchanged after an uncertain result

Request
curl -X DELETE "http://localhost:3000/api/v1/subscribers/6650f1c2e9b1d4a012345678/sms/phone" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Withdraw subscriber SMS consent

POST/api/v1/subscribers/{id}/sms/subscriptions/{subscriptionId}/withdraw

Withdraws SMS permission for one newsletter, cancels pending confirmation and keeps other preferences unchanged. Cannot grant consent.

MCP toolwithdraw_subscriber_smsKeyaudience:write + audience:readSafe to repeat
Parameter
idrequired

path · string

The resource ID in this account

subscriptionIdrequired

path · string

The resource ID in this account

expectedVersionrequired

body · integer

The current version; stale changes are rejected

requestIdrequired

body · string

A unique request ID; reuse unchanged after an uncertain result

Request
curl -X POST "http://localhost:3000/api/v1/subscribers/6650f1c2e9b1d4a012345678/sms/subscriptions/6650f1c2e9b1d4a012345678/withdraw" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"expectedVersion":"…","requestId":"…"}'

Contacts

Newsletter-specific compatibility actions. On v2, a contact ID is a NewsletterSubscription ID; add is organizational by default; explicit subscribe:true records owner authorization for unrestricted subscriptions without recipient confirmation. Imports do not imply consent, no welcome/sequence mail starts, and delete removes only that subscription.

Inspect proposed import recipients

POST/api/v1/contacts/import-preview

Preview only. No contacts or consent were changed. Reads consent for the selected newsletter on v2 accounts, current account-wide consent on v1 accounts, and independent restrictions for up to 200 addresses in one request snapshot. Different requests do not share a snapshot; these diagnostics never authorize delivery.

MCP toolinspect_import_recipientsKeyaudience:readRead-onlySafe to repeat
Parameter
newsletterrequired

body · string

Newsletter ID or slug in this account

recordsrequired

body · object[]

One through 200 distinct normalized addresses to inspect; no records are written

records[].ordinalrequired

body · integer

Unique address ordinal in the local analysis, 1 through 25000

records[].emailrequired

body · string

Normalized email; lowercase, no surrounding whitespace, preserving dots and plus suffixes

Request
curl -X POST "http://localhost:3000/api/v1/contacts/import-preview" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"newsletter":"weekly","records":"…"}'

Create subscriber import

POST/api/v1/subscriber-imports

Bounded durable CSV import for one newsletter. Simple csv requires one profiles file and an existing target group, without migration evidence. New simple CSV runs authorize eligible blank/active subscriptions after exact-plan approval; existing restrictions and older runs retain their meaning. Owner-authorized approval and apply also require sending permission for scoped agents. Classic source active status alone never grants consent. No email, DOI or sequence is started. Verify your export columns and statuses; real Classic export qualification remains separate.

MCP toolcreate_subscriber_importKeyaudience:write + audience:readSafe to repeat
Parameter
newsletterIdrequired

body · string

The one existing newsletter receiving this import.

sourceKindrequired

body · "mailerlite-classic-csv" | "csv"

csv for a simple owner-authorized group import, or mailerlite-classic-csv for the advanced migration preset.

requestKeyrequired

body · string

Stable idempotency key; retry exactly the same payload with this key.

filesrequired

body · object[]

Confirmed file roles, headers and owner-declared source byte hashes; no raw file is stored.

files[].fileRolerequired

body · "profiles" | "statuses" | "memberships"

files[].headerrequired

body · string[]

files[].delimiterrequired

body · "comma" | "semicolon" | "tab"

files[].declaredRowsrequired

body · integer

files[].byteCountrequired

body · integer

files[].ownerDeclaredFileSha256required

body · string

mappingrequired

body · object

Explicit header, source status, group delimiter and timestamp mappings.

mapping.profilesrequired

body · object

mapping.statuses

body · object

mapping.memberships

body · object

mapping.timestampFormat

body · "iso-utc" | "classic-utc"

mapping.timezone

body · string

mapping.groupSeparator

body · string

mapping.statusValues

body · object

sourceContext

body · object

Required only for Classic: source account/newsletter identity and UTC extraction time. Omit for csv.

sourceContext.sourceAccountIdrequired

body · string

sourceContext.sourceNewsletterIdrequired

body · string

sourceContext.extractedAtrequired

body · string

groupMappings

body · object[]

Explicit source group to newsletter-scoped existing or new group mapping.

groupMappings[].sourceGroupIdrequired

body · string

groupMappings[].targetrequired

body · object

constantGroup

body · object

For csv, one required existing group in the target newsletter. Optional for Classic. Membership never grants consent.

evidencePolicy

body · object

csv requires only version csv_facts_v1; new simple runs activate eligible subscriptions through owner authorization, without claiming recipient confirmation. Classic retains its closed facts-only or reviewed source policy.

evidencePolicy.versionrequired

body · "classic_csv_facts_v1" | "classic_confirmation_record_v1" | "csv_facts_v1"

evidencePolicy.sourceNewsletterId

body · string

evidencePolicy.artifactSha256

body · string

evidencePolicy.acknowledgedSourceAssertion

body · boolean

Request
curl -X POST "http://localhost:3000/api/v1/subscriber-imports" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"newsletterId":"…","sourceKind":"…","requestKey":"…","files":"…","mapping":"…"}'

Upload subscriber import chunk

POST/api/v1/subscriber-imports/{id}/chunks

Bounded durable CSV import for one newsletter. Simple csv requires one profiles file and an existing target group, without migration evidence. New simple CSV runs authorize eligible blank/active subscriptions after exact-plan approval; existing restrictions and older runs retain their meaning. Owner-authorized approval and apply also require sending permission for scoped agents. Classic source active status alone never grants consent. No email, DOI or sequence is started. Verify your export columns and statuses; real Classic export qualification remains separate.

MCP toolupload_subscriber_import_chunkKeyaudience:write + audience:readSafe to repeat
Parameter
idrequired

path · string

The opaque import run ID in this account.

revisionrequired

body · integer

The latest run revision; stale writes return a conflict.

requestKeyrequired

body · string

Stable idempotency key; retry exactly the same payload with this key.

fileRolerequired

body · "profiles" | "statuses" | "memberships"

The declared file role for this chunk.

chunkIndexrequired

body · integer

Contiguous zero-based chunk index for this role.

rowsrequired

body · object[]

Up to 200 raw cell arrays with contiguous one-based source ordinals.

rows[].ordinalrequired

body · integer

rows[].cellsrequired

body · string[]

declaredDigestrequired

body · string

SHA256 of JSON.stringify(rows), verified independently by the server.

Request
curl -X POST "http://localhost:3000/api/v1/subscriber-imports/6650f1c2e9b1d4a012345678/chunks" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"revision":"…","requestKey":"…","fileRole":"…","chunkIndex":"…","rows":"…","declaredDigest":"…"}'

Stage subscriber import

POST/api/v1/subscriber-imports/{id}/stage

Bounded durable CSV import for one newsletter. Simple csv requires one profiles file and an existing target group, without migration evidence. New simple CSV runs authorize eligible blank/active subscriptions after exact-plan approval; existing restrictions and older runs retain their meaning. Owner-authorized approval and apply also require sending permission for scoped agents. Classic source active status alone never grants consent. No email, DOI or sequence is started. Verify your export columns and statuses; real Classic export qualification remains separate.

MCP toolstage_subscriber_importKeyaudience:write + audience:readSafe to repeat
Parameter
idrequired

path · string

The opaque import run ID in this account.

revisionrequired

body · integer

The latest run revision; stale writes return a conflict.

requestKeyrequired

body · string

Stable idempotency key; retry exactly the same payload with this key.

uploadedCountsrequired

body · object

Exact uploaded row counts per role.

canonicalDigestrequired

body · string

Authoritative canonical digest returned by the last upload.

Request
curl -X POST "http://localhost:3000/api/v1/subscriber-imports/6650f1c2e9b1d4a012345678/stage" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"revision":"…","requestKey":"…","uploadedCounts":"…","canonicalDigest":"…"}'

Preview subscriber import

POST/api/v1/subscriber-imports/{id}/preview

Bounded durable CSV import for one newsletter. Simple csv requires one profiles file and an existing target group, without migration evidence. New simple CSV runs authorize eligible blank/active subscriptions after exact-plan approval; existing restrictions and older runs retain their meaning. Owner-authorized approval and apply also require sending permission for scoped agents. Classic source active status alone never grants consent. No email, DOI or sequence is started. Verify your export columns and statuses; real Classic export qualification remains separate.

MCP toolpreview_subscriber_importKeyaudience:write + audience:readSafe to repeat
Parameter
idrequired

path · string

The opaque import run ID in this account.

revisionrequired

body · integer

The latest run revision; stale writes return a conflict.

requestKeyrequired

body · string

Stable idempotency key; retry exactly the same payload with this key.

Request
curl -X POST "http://localhost:3000/api/v1/subscriber-imports/6650f1c2e9b1d4a012345678/preview" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"revision":"…","requestKey":"…"}'

Get subscriber import

GET/api/v1/subscriber-imports/{id}

Bounded durable CSV import for one newsletter. Simple csv requires one profiles file and an existing target group, without migration evidence. New simple CSV runs authorize eligible blank/active subscriptions after exact-plan approval; existing restrictions and older runs retain their meaning. Owner-authorized approval and apply also require sending permission for scoped agents. Classic source active status alone never grants consent. No email, DOI or sequence is started. Verify your export columns and statuses; real Classic export qualification remains separate.

MCP toolget_subscriber_importKeyaudience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The opaque import run ID in this account.

Request
curl "http://localhost:3000/api/v1/subscriber-imports/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

List subscriber imports

GET/api/v1/subscriber-imports

Bounded durable CSV import for one newsletter. Simple csv requires one profiles file and an existing target group, without migration evidence. New simple CSV runs authorize eligible blank/active subscriptions after exact-plan approval; existing restrictions and older runs retain their meaning. Owner-authorized approval and apply also require sending permission for scoped agents. Classic source active status alone never grants consent. No email, DOI or sequence is started. Verify your export columns and statuses; real Classic export qualification remains separate.

MCP toollist_subscriber_importsKeyaudience:readRead-onlySafe to repeat
Parameter
cursor

query · string

Opaque signed continuation cursor from the preceding page.

limit

query · integer

Maximum bounded page size.

Request
curl "http://localhost:3000/api/v1/subscriber-imports" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Get subscriber import rows

GET/api/v1/subscriber-imports/{id}/rows

Bounded durable CSV import for one newsletter. Simple csv requires one profiles file and an existing target group, without migration evidence. New simple CSV runs authorize eligible blank/active subscriptions after exact-plan approval; existing restrictions and older runs retain their meaning. Owner-authorized approval and apply also require sending permission for scoped agents. Classic source active status alone never grants consent. No email, DOI or sequence is started. Verify your export columns and statuses; real Classic export qualification remains separate.

MCP toolget_subscriber_import_rowsKeyaudience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The opaque import run ID in this account.

cursor

query · string

Opaque signed continuation cursor from the preceding page.

limit

query · integer

Maximum bounded page size.

resultCode

query · string

Optional exact safe result classification filter.

Request
curl "http://localhost:3000/api/v1/subscriber-imports/6650f1c2e9b1d4a012345678/rows" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Approve subscriber import

POST/api/v1/subscriber-imports/{id}/approve

Bounded durable CSV import for one newsletter. Simple csv requires one profiles file and an existing target group, without migration evidence. New simple CSV runs authorize eligible blank/active subscriptions after exact-plan approval; existing restrictions and older runs retain their meaning. Owner-authorized approval and apply also require sending permission for scoped agents. Classic source active status alone never grants consent. No email, DOI or sequence is started. Verify your export columns and statuses; real Classic export qualification remains separate.

MCP toolapprove_subscriber_importKeyaudience:write + audience:readSafe to repeat
Parameter
idrequired

path · string

The opaque import run ID in this account.

revisionrequired

body · integer

The latest run revision; stale writes return a conflict.

requestKeyrequired

body · string

Stable idempotency key; retry exactly the same payload with this key.

planDigestrequired

body · string

The exact completed preview plan digest being approved or applied.

evidenceDigestrequired

body · string

The exact retained source evidence digest reviewed by the owner.

acknowledgementrequired

body · "approve-reviewed-import" | "approve-owner-authorized-import"

Use approve-owner-authorized-import only for subscriptionMode owner-authorized to authorize eligible subscriptions; organizational and reviewed-evidence runs require approve-reviewed-import. This approves the exact plan, without claiming recipient confirmation.

Request
curl -X POST "http://localhost:3000/api/v1/subscriber-imports/6650f1c2e9b1d4a012345678/approve" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"revision":"…","requestKey":"…","planDigest":"…","evidenceDigest":"…","acknowledgement":"…"}'

Apply subscriber import

POST/api/v1/subscriber-imports/{id}/apply

Bounded durable CSV import for one newsletter. Simple csv requires one profiles file and an existing target group, without migration evidence. New simple CSV runs authorize eligible blank/active subscriptions after exact-plan approval; existing restrictions and older runs retain their meaning. Owner-authorized approval and apply also require sending permission for scoped agents. Classic source active status alone never grants consent. No email, DOI or sequence is started. Verify your export columns and statuses; real Classic export qualification remains separate.

MCP toolapply_subscriber_importKeyaudience:write + audience:readSafe to repeat
Parameter
idrequired

path · string

The opaque import run ID in this account.

revisionrequired

body · integer

The latest run revision; stale writes return a conflict.

requestKeyrequired

body · string

Stable idempotency key; retry exactly the same payload with this key.

planDigestrequired

body · string

The exact completed preview plan digest being approved or applied.

Request
curl -X POST "http://localhost:3000/api/v1/subscriber-imports/6650f1c2e9b1d4a012345678/apply" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"revision":"…","requestKey":"…","planDigest":"…"}'

Cancel subscriber import

POST/api/v1/subscriber-imports/{id}/cancel

Bounded durable CSV import for one newsletter. Simple csv requires one profiles file and an existing target group, without migration evidence. New simple CSV runs authorize eligible blank/active subscriptions after exact-plan approval; existing restrictions and older runs retain their meaning. Owner-authorized approval and apply also require sending permission for scoped agents. Classic source active status alone never grants consent. No email, DOI or sequence is started. Verify your export columns and statuses; real Classic export qualification remains separate.

MCP toolcancel_subscriber_importKeyaudience:write + audience:readCan't be undoneSafe to repeat
Parameter
idrequired

path · string

The opaque import run ID in this account.

revisionrequired

body · integer

The latest run revision; stale writes return a conflict.

requestKeyrequired

body · string

Stable idempotency key; retry exactly the same payload with this key.

Request
curl -X POST "http://localhost:3000/api/v1/subscriber-imports/6650f1c2e9b1d4a012345678/cancel" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"revision":"…","requestKey":"…"}'

Export subscriber import report

POST/api/v1/subscriber-imports/{id}/report

Bounded durable CSV import for one newsletter. Simple csv requires one profiles file and an existing target group, without migration evidence. New simple CSV runs authorize eligible blank/active subscriptions after exact-plan approval; existing restrictions and older runs retain their meaning. Owner-authorized approval and apply also require sending permission for scoped agents. Classic source active status alone never grants consent. No email, DOI or sequence is started. Verify your export columns and statuses; real Classic export qualification remains separate.

MCP toolexport_subscriber_import_reportKeyaudience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The opaque import run ID in this account.

cursor

body · string

Opaque signed continuation cursor from the preceding page.

limit

body · integer

Maximum bounded page size.

resultCode

body · string

Optional exact safe result classification filter.

Request
curl -X POST "http://localhost:3000/api/v1/subscriber-imports/6650f1c2e9b1d4a012345678/report" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

List contacts

GET/api/v1/contacts

Lists newsletter contacts, newest signups first, 50 a page. On v2 each contact ID is a Subscription ID and email comes from its Subscriber profile. Filter by newsletter, status or the start of the email address; segment filtering remains a v1 option. Pass nextCursor back as cursor. counts has every status for the same filters.

MCP toollist_contactsKeyaudience:readRead-onlySafe to repeat
Parameter
newsletter

query · string

Only this newsletter's: its ID or slug. Default: every newsletter.

status

query · "active" | "pending" | "unsubscribed" | "bounced" | "complained" | "dormant"

Only contacts with this status

segment

query · string

Only the contacts a segment picks (its ID, from list_segments), whatever their status unless status is given. With newsletter, one of that newsletter's segments.

search

query · string

Contacts whose email starts with this

limit

query · integer

Contacts per page, 50 by default, 100 at most

cursor

query · string

nextCursor from the previous page

Request
curl "http://localhost:3000/api/v1/contacts?status=active&search=jane" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Get a contact

GET/api/v1/contacts/{id}

Gets one newsletter contact by Subscription ID on v2 (legacy Contact ID on v1), or by email when unambiguous. Status and engagement belong to that newsletter.

MCP toolget_contactKeyaudience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The contact's ID or email address

newsletter

query · string

The newsletter's ID or slug, needed for an email address that is a contact of several newsletters

Request
curl "http://localhost:3000/api/v1/contacts/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Add a contact

POST/api/v1/contacts

Adds a contact to one newsletter. With subscribe:true on a ready unified audience, the owner authorizes a new unrestricted subscription to receive issues without recipient confirmation. Omit subscribe to add an organizational contact only. Existing withdrawals, delivery blocks and dormant states remain unchanged. Never sends a welcome or confirmation message. Requires full access.

MCP tooladd_contactKeyaudience:write + audience:readReaches outside ApresMail
Parameter
newsletter

body · string

The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest.

emailrequired

body · string

The subscriber's email address

source

body · string

Where they signed up, e.g. website. Default: api.

subscribe

body · boolean

The owner authorizes this newsletter subscription without recipient confirmation. Unified audience and full access required. Never restores a withdrawal or removes delivery blocks.

resubscribe

body · boolean

Legacy option: true is rejected. Use a recipient-confirmed signup to renew consent.

ip

body · string

The visitor's IP address: one visitor gets 5 signups in 10 minutes

Request
curl -X POST "http://localhost:3000/api/v1/contacts" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"jane@example.com","source":"website"}'

Change a contact's status

PATCH/api/v1/contacts/{id}

Changes engagement status for an already-consented newsletter contact, or withdraws only its newsletter consent on v2 (account-wide on v1). Operator input cannot activate pending or withdrawn consent. No email is sent.

MCP toolupdate_contact_statusKeyaudience:write + audience:readCan't be undoneSafe to repeat
Parameter
idrequired

path · string

The contact's ID or email address

newsletter

body · string

The newsletter's ID or slug, needed for an email address that is a contact of several newsletters

statusrequired

body · "active" | "dormant" | "unsubscribed"

active, dormant or unsubscribed

consent

body · boolean

Legacy assertion; it never grants or restores marketing consent

Request
curl -X PATCH "http://localhost:3000/api/v1/contacts/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status":"dormant"}'

Delete a contact

DELETE/api/v1/contacts/{id}

Deletes one newsletter contact. On v2 its ID is a Subscription ID: only that newsletter is withdrawn and soft-deleted, while the Subscriber and other newsletters remain. On v1, the legacy deletion and account-wide recipient rules apply. Reimporting never restores consent.

MCP tooldelete_contactKeyaudience:write + audience:readCan't be undoneSafe to repeat
Parameter
idrequired

path · string

The contact's ID or email address

newsletter

query · string

The newsletter's ID or slug, needed for an email address that is a contact of several newsletters

Request
curl -X DELETE "http://localhost:3000/api/v1/contacts/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Import contacts

POST/api/v1/contacts/import

Adds up to 1000 contacts per call, with the same checks as the dashboard's CSV import: invalid, misspelled (gmial.com…), spam trap, role (info@, support@…), throwaway, duplicate and suppressed addresses, undeliverable ones (ApresMail knows they can't receive email: they hard bounced or hit a spam trap, from any sender on ApresMail), and addresses on domains that can't receive email, are left out and counted. consent must be true: "These people agreed to receive my emails". Existing contacts keep their status unless a row gives a stricter one (unsubscribed, bounced, complained), which is final. No welcome emails go out. For more rows, send the next chunk with the importId of the first.

MCP toolimport_contactsKeyaudience:write + audience:readCan't be undoneSafe to repeat
Parameter
newsletter

body · string

The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest.

consentrequired

body · boolean

Must be true: These people agreed to receive my emails. Bought or scraped lists aren't allowed.

contactsrequired

body · object[]

The rows, 1000 at most

contacts[].emailrequired

body · string

Invalid addresses are left out and counted

contacts[].status

body · "active" | "dormant" | "unsubscribed" | "bounced" | "complained"

active (default), dormant, unsubscribed, bounced or complained

contacts[].subscribedAt

body · string

When they signed up, ISO 8601

contacts[].emailsReceived

body · number

Emails they got on the previous platform

contacts[].openRate

body · number

0 to 1, from the previous platform: sends reach the most engaged first

contacts[].clickRate

body · number

0 to 1, from the previous platform

importId

body · string

The importId of the first chunk, to add rows to the same import

duplicates

body · integer

Duplicates you removed before sending, counted in the import's report

Request
curl -X POST "http://localhost:3000/api/v1/contacts/import" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"consent":true,"contacts":[{"email":"jane@example.com","subscribedAt":"2025-03-01T00:00:00Z"},{"email":"sam@example.com","status":"unsubscribed"}]}'

Export contacts

GET/api/v1/contacts/export

Makes a CSV download link for the contacts matching the filters, valid for an hour, no API key needed to open it. The columns go back in through the import as they are.

MCP toolexport_contactsKeyaudience:readRead-onlySafe to repeat
Parameter
newsletter

query · string

Only this newsletter's: its ID or slug. Default: every newsletter.

status

query · "active" | "pending" | "unsubscribed" | "bounced" | "complained" | "dormant"

Only contacts with this status

segment

query · string

Only the contacts a segment picks (its ID, from list_segments), whatever their status unless status is given. With newsletter, one of that newsletter's segments.

search

query · string

Contacts whose email starts with this

Request
curl "http://localhost:3000/api/v1/contacts/export?status=active" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Subscribers

Canonical v2 profiles and newsletter-specific subscriptions, groups and consent events. Writes are scoped and idempotent; no action grants consent.

List subscribers

GET/api/v1/subscribers

Lists canonical profiles, fifty raw records per keyset page. Newsletter, consent and group filters never grant consent.

MCP toollist_subscribersKeyaudience:readRead-onlySafe to repeat
Parameter
email

query · string

Exact email address to look up; cannot be combined with a cursor

newsletterId

query · string

An ID in this account

consentState

query · "none" | "active" | "withdrawn"

Consent state within the selected newsletter; requires newsletterId

groupId

query · string

An ID in this account

cursor

query · string

Opaque continuation cursor from the previous page; omit for the first page

Request
curl "http://localhost:3000/api/v1/subscribers" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Get a subscriber

GET/api/v1/subscribers/{id}

Gets one live canonical profile in this account.

MCP toolget_subscriberKeyaudience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

An ID in this account

Request
curl "http://localhost:3000/api/v1/subscribers/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

List subscriber subscriptions

GET/api/v1/subscribers/{id}/subscriptions

Lists a subscriber's newsletter-specific subscriptions, fifty raw records per page.

MCP toollist_subscriptionsKeyaudience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

An ID in this account

cursor

query · string

Opaque continuation cursor from the previous page; omit for the first page

Request
curl "http://localhost:3000/api/v1/subscribers/6650f1c2e9b1d4a012345678/subscriptions" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

List subscription groups

GET/api/v1/subscriptions/{id}/groups

Lists only groups attached to this subscription's newsletter.

MCP toollist_subscription_groupsKeyaudience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

An ID in this account

cursor

query · string

Opaque continuation cursor from the previous page; omit for the first page

Request
curl "http://localhost:3000/api/v1/subscriptions/6650f1c2e9b1d4a012345678/groups" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

List subscription consent events

GET/api/v1/subscriptions/{id}/events

Lists newsletter-scoped consent evidence without private references or legacy account grants.

MCP toollist_subscription_eventsKeyaudience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

An ID in this account

cursor

query · string

Opaque continuation cursor from the previous page; omit for the first page

Request
curl "http://localhost:3000/api/v1/subscriptions/6650f1c2e9b1d4a012345678/events" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Update subscriber profile

PATCH/api/v1/subscribers/{id}

Changes only the first name with profile version compare-and-set. Never grants consent.

MCP toolupdate_subscriberKeyaudience:write + audience:readSafe to repeat
Parameter
idrequired

path · string

An ID in this account

profileVersionrequired

body · integer

Current profile version for conflict detection

firstNamerequired

body · string | null

New first name, or null to clear it

requestIdrequired

body · string

Stable UUID for this exact operation

Request
curl -X PATCH "http://localhost:3000/api/v1/subscribers/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"profileVersion":"…","firstName":"…","requestId":"…"}'

Withdraw subscription

POST/api/v1/subscriptions/{id}/withdraw

Withdraws only this newsletter's current consent epoch. Replays with the same requestId return the original result.

MCP toolwithdraw_subscriptionKeyaudience:write + audience:readCan't be undoneSafe to repeat
Parameter
idrequired

path · string

An ID in this account

requestIdrequired

body · string

Stable UUID for this exact operation

Request
curl -X POST "http://localhost:3000/api/v1/subscriptions/6650f1c2e9b1d4a012345678/withdraw" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"requestId":"…"}'

Delete a subscription

DELETE/api/v1/subscriptions/{id}

Soft-deletes one newsletter subscription, withdraws consent and removes its organizational memberships. The profile and other newsletters remain.

MCP tooldelete_subscriptionKeyaudience:write + audience:readCan't be undoneSafe to repeat
Parameter
idrequired

path · string

An ID in this account

requestIdrequired

query · string

Stable UUID for this exact operation

Request
curl -X DELETE "http://localhost:3000/api/v1/subscriptions/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Erase subscriber

DELETE/api/v1/subscribers/{id}

Starts account-wide privacy erasure for this profile and all its newsletter subscriptions. Retains tombstone IDs.

MCP toolerase_subscriberKeyaudience:write + audience:readCan't be undoneSafe to repeat
Parameter
idrequired

path · string

An ID in this account

requestIdrequired

query · string

Stable UUID for this exact operation

Request
curl -X DELETE "http://localhost:3000/api/v1/subscribers/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Recipients

Deprecated v1 account-wide consent reads. V2 accounts use Subscribers actions and receive conflict for these legacy tools.

List recipients through the deprecated endpoint

GET/api/v1/recipients

Deprecated legacy account-wide consent read. On a v2 account this always returns conflict; use list_subscribers and list_subscriptions. On v1, exact email search only; erased records are omitted.

MCP toollist_recipientsKeyaudience:readRead-onlySafe to repeat
Parameter
state

query · "none" | "active" | "withdrawn"

Only recipients with this canonical consent state; omitted means all states

email

query · string

Exact email match, preserving plus suffixes and dots; cannot be combined with cursor

cursor

query · string

The previous page nextCursor with the same filters; never combine with email

Request
curl "http://localhost:3000/api/v1/recipients" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Get a recipient through the deprecated endpoint

GET/api/v1/recipients/{id}

Deprecated legacy account-wide consent read. On a v2 account this always returns conflict; use get_subscriber and list_subscriptions. On v1, erased and foreign records return not_found.

MCP toolget_recipientKeyaudience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The canonical recipient ID in this account

Request
curl "http://localhost:3000/api/v1/recipients/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Segments

Saved conditions that pick some of a newsletter's contacts by engagement, signup date, source or address, to send campaigns to them only.

List segments

GET/api/v1/segments

Lists segments, oldest first, with their conditions in words and how many active contacts each picks now.

MCP toollist_segmentsKeyaudience:readRead-onlySafe to repeat
Parameter
newsletter

query · string

Only this newsletter's: its ID or slug. Default: every newsletter.

Request
curl "http://localhost:3000/api/v1/segments" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Get a segment

GET/api/v1/segments/{id}

Gets one segment with its conditions and how many active contacts it picks now.

MCP toolget_segmentKeyaudience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The segment's ID

Request
curl "http://localhost:3000/api/v1/segments/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Count a segment's contacts

POST/api/v1/segments/count

Counts the active contacts some conditions would pick, without saving anything: try them before create_segment.

MCP toolcount_segmentKeyaudience:readRead-onlySafe to repeat
Parameter
newsletter

body · string

The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest.

match

body · "all" | "any"

all: contacts meeting every condition (the default). any: contacts meeting at least one.

conditionsrequired

body · object[]

The conditions, 10 at most. Dates count back from each send, so "within 30 days" moves with time.

conditions[].fieldrequired

body · "opened" | "clicked" | "missed_issues" | "emails_opened" | "signed_up" | "source" | "email"

opened, clicked: the last open or click (a click counts as an open). missed_issues: issues received in a row without opening or clicking any. emails_opened: emails opened in all. signed_up: the signup date. source: where the contact came from (website, import, dashboard, api, or a source an API caller gave). email: the address.

conditions[].oprequired

body · "within" | "not_within" | "never" | "at_least" | "less_than" | "before" | "since" | "is" | "is_not" | "contains" | "ends_with"

opened, clicked: within, not_within (days) or never. missed_issues, emails_opened: at_least or less_than (a number). signed_up: within, not_within (days), before or since (a date). source: is or is_not. email: contains or ends_with.

conditions[].value

body · number | string

Days (1 to 3650) for within and not_within, a number for at_least and less_than, YYYY-MM-DD (UTC) for before and since, text for the rest. None for never.

Request
curl -X POST "http://localhost:3000/api/v1/segments/count" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"conditions":[{"field":"opened","op":"within","value":30}]}'

Create a segment

POST/api/v1/segments

Saves conditions that pick some of a newsletter's contacts, to send campaigns to them only (segment on update_campaign, send_campaign or schedule_campaign). Contacts join and leave it as they meet the conditions.

MCP toolcreate_segmentKeyaudience:write + audience:read
Parameter
newsletter

body · string

The newsletter's ID or slug. Default: the account's first newsletter, the one it has had longest.

namerequired

body · string

The segment's name, 60 characters at most

match

body · "all" | "any"

all: contacts meeting every condition (the default). any: contacts meeting at least one.

conditionsrequired

body · object[]

The conditions, 10 at most. Dates count back from each send, so "within 30 days" moves with time.

conditions[].fieldrequired

body · "opened" | "clicked" | "missed_issues" | "emails_opened" | "signed_up" | "source" | "email"

opened, clicked: the last open or click (a click counts as an open). missed_issues: issues received in a row without opening or clicking any. emails_opened: emails opened in all. signed_up: the signup date. source: where the contact came from (website, import, dashboard, api, or a source an API caller gave). email: the address.

conditions[].oprequired

body · "within" | "not_within" | "never" | "at_least" | "less_than" | "before" | "since" | "is" | "is_not" | "contains" | "ends_with"

opened, clicked: within, not_within (days) or never. missed_issues, emails_opened: at_least or less_than (a number). signed_up: within, not_within (days), before or since (a date). source: is or is_not. email: contains or ends_with.

conditions[].value

body · number | string

Days (1 to 3650) for within and not_within, a number for at_least and less_than, YYYY-MM-DD (UTC) for before and since, text for the rest. None for never.

Request
curl -X POST "http://localhost:3000/api/v1/segments" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Engaged","conditions":[{"field":"opened","op":"within","value":30}]}'

Update a segment

PATCH/api/v1/segments/{id}

Renames a segment or changes its conditions. Send only what changes; conditions replace the old ones. Campaigns going to it, scheduled ones included, use the new conditions when they go out.

MCP toolupdate_segmentKeyaudience:write + audience:readSafe to repeat
Parameter
idrequired

path · string

The segment's ID

name

body · string

The segment's name, 60 characters at most

match

body · "all" | "any"

all: contacts meeting every condition (the default). any: contacts meeting at least one.

conditions

body · object[]

The conditions, 10 at most. Dates count back from each send, so "within 30 days" moves with time.

conditions[].fieldrequired

body · "opened" | "clicked" | "missed_issues" | "emails_opened" | "signed_up" | "source" | "email"

opened, clicked: the last open or click (a click counts as an open). missed_issues: issues received in a row without opening or clicking any. emails_opened: emails opened in all. signed_up: the signup date. source: where the contact came from (website, import, dashboard, api, or a source an API caller gave). email: the address.

conditions[].oprequired

body · "within" | "not_within" | "never" | "at_least" | "less_than" | "before" | "since" | "is" | "is_not" | "contains" | "ends_with"

opened, clicked: within, not_within (days) or never. missed_issues, emails_opened: at_least or less_than (a number). signed_up: within, not_within (days), before or since (a date). source: is or is_not. email: contains or ends_with.

conditions[].value

body · number | string

Days (1 to 3650) for within and not_within, a number for at_least and less_than, YYYY-MM-DD (UTC) for before and since, text for the rest. None for never.

Request
curl -X PATCH "http://localhost:3000/api/v1/segments/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Engaged this quarter","conditions":[{"field":"opened","op":"within","value":90}]}'

Delete a segment

DELETE/api/v1/segments/{id}

Deletes a segment. Its contacts stay as they are. A scheduled, sending or paused campaign going to it answers conflict: change who it goes to first. Drafts going to it can't be sent until they get another segment or none.

MCP tooldelete_segmentKeyaudience:write + audience:readCan't be undoneSafe to repeat
Parameter
idrequired

path · string

The segment's ID

Request
curl -X DELETE "http://localhost:3000/api/v1/segments/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Sequences

Import a Classic sequence draft

POST/api/v1/sequences/import-classic

Imports a reviewed MailerLite Classic migration bundle as a draft. Repeating the same source account, workflow and target returns the original draft; changed content conflicts. Does not publish, enroll participants or send.

MCP toolimport_classic_sequenceKeycontent:writeSafe to repeat
Parameter
newsletterIdrequired

body · string

The existing target newsletter in this account; its sender settings apply.

bundlerequired

body · object

One explicitly authored Classic migration bundle, not a native automation export; at most 512 KiB.

bundle.formatrequired

body · string

bundle.versionrequired

body · number

bundle.sourceAccountrequired

body · string

bundle.sourceSequenceIdrequired

body · string

bundle.namerequired

body · string

bundle.triggerrequired

body · object

bundle.entryPolicy

body · "once" | "on_new_join"

Once per subscriber by default. on_new_join requires a fresh group join after the previous run ends; current runs never overlap.

bundle.schedulerequired

body · object

bundle.entryStepIdrequired

body · string

bundle.stepsrequired

body · any[]

groupMappings

body · object[]

Exact source group references mapped to groups in the target newsletter; omitted groups stay unresolved.

groupMappings[].sourceGroupIdrequired

body · string

groupMappings[].targetGroupIdrequired

body · string

contentReviewedrequired

body · boolean

Confirm manual review of original unpersonalized content, retained external links/assets and timing; this does not grant consent or publish.

Request
curl -X POST "http://localhost:3000/api/v1/sequences/import-classic" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"newsletterId":"…","bundle":"…","contentReviewed":"…"}'

List sequences

GET/api/v1/sequences

Lists account-wide email sequences without enrolling or sending.

MCP toollist_sequencesKeycontent:readRead-onlySafe to repeat
Parameter
page

query · integer

One-based result page, fifty entries per page

state

query · "draft" | "active" | "paused" | "stopped" | "archived"

Only sequences in this lifecycle state

Request
curl "http://localhost:3000/api/v1/sequences" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Get a sequence

GET/api/v1/sequences/{id}

Reads the saved draft and published revision identity.

MCP toolget_sequenceKeycontent:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The resource ID in the authenticated account

Request
curl "http://localhost:3000/api/v1/sequences/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Create a sequence

POST/api/v1/sequences

Creates a draft only; reuse requestId after a lost response. Does not enroll or send.

MCP toolcreate_sequenceKeycontent:writeSafe to repeat
Parameter
requestIdrequired

body · string

A stable UUID for this exact operation; reuse it only to retry the same payload

namerequired

body · string

A short name for the sequence

newsletterIdrequired

body · string

The resource ID in the authenticated account

Request
curl -X POST "http://localhost:3000/api/v1/sequences" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"requestId":"…","name":"…","newsletterId":"…"}'

Save a sequence

PATCH/api/v1/sequences/{id}

Saves the exact draft using its expected version and stable request identity; existing enrollments are unchanged.

MCP toolupdate_sequenceKeycontent:writeSafe to repeat
Parameter
idrequired

path · string

The resource ID in the authenticated account

requestIdrequired

body · string

A stable UUID for this exact operation; reuse it only to retry the same payload

expectedVersionrequired

body · integer

The expected version returned by the latest read of this resource

namerequired

body · string

A short name for the sequence

draftrequired

body · object

The complete saved trigger, graph and send schedule

draft.triggerrequired

body · any

draft.entryPolicy

body · "once" | "on_new_join"

Once per subscriber by default. on_new_join requires a fresh group join after the previous run ends; current runs never overlap.

draft.entryNodeIdrequired

body · string

draft.nodesrequired

body · any[]

draft.schedulerequired

body · object

Request
curl -X PATCH "http://localhost:3000/api/v1/sequences/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"requestId":"…","expectedVersion":"…","name":"…","draft":"…"}'

Preview a sequence

POST/api/v1/sequences/{id}/preview

Validates and renders a saved draft. Simulates synthetic facts without creating recipients, jobs or sending.

MCP toolpreview_sequenceKeycontent:writeRead-onlySafe to repeat
Parameter
idrequired

path · string

The resource ID in the authenticated account

expectedVersionrequired

body · integer

The expected version returned by the latest read of this resource

simulation

body · object

Synthetic clock, memberships and origin form for a read-only path simulation

simulation.atrequired

body · string

simulation.memberGroupIdsrequired

body · string[]

simulation.originFormIdrequired

body · string | null

Request
curl -X POST "http://localhost:3000/api/v1/sequences/6650f1c2e9b1d4a012345678/preview" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"expectedVersion":"…"}'

Publish a sequence

POST/api/v1/sequences/{id}/publish

Approves the exact preview as an immutable revision for future trigger events. A paused sequence remains paused.

MCP toolpublish_sequenceKeycontent:write + messages:sendSafe to repeat
Parameter
idrequired

path · string

The resource ID in the authenticated account

requestIdrequired

body · string

A stable UUID for this exact operation; reuse it only to retry the same payload

expectedVersionrequired

body · integer

The expected version returned by the latest read of this resource

previewDigestrequired

body · string

The digest from previewing this exact saved version

Request
curl -X POST "http://localhost:3000/api/v1/sequences/6650f1c2e9b1d4a012345678/publish" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"requestId":"…","expectedVersion":"…","previewDigest":"…"}'

Change sequence state

POST/api/v1/sequences/{id}/lifecycle

Pauses, resumes, permanently stops or archives a sequence. Resume never replays historical trigger events.

MCP toolsequence_lifecycleKeycontent:writeSafe to repeat
Parameter
idrequired

path · string

The resource ID in the authenticated account

requestIdrequired

body · string

A stable UUID for this exact operation; reuse it only to retry the same payload

expectedLifecycleVersionrequired

body · integer

The expected version returned by the latest read of this resource

actionrequired

body · "pause" | "resume" | "stop" | "archive"

The lifecycle transition to apply

Request
curl -X POST "http://localhost:3000/api/v1/sequences/6650f1c2e9b1d4a012345678/lifecycle" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"requestId":"…","expectedLifecycleVersion":"…","action":"…"}'

List sequence participants

GET/api/v1/sequences/{id}/participants

Lists participant versions, status and next due times within this account.

MCP toollist_sequence_participantsKeyaudience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The resource ID in the authenticated account

page

query · integer

One-based result page, fifty entries per page

state

query · "waiting" | "active" | "unknown" | "completed" | "stopped" | "expired" | "failed"

Only participants in this execution state

Request
curl "http://localhost:3000/api/v1/sequences/6650f1c2e9b1d4a012345678/participants" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Get sequence participant

GET/api/v1/sequences/{id}/participants/{enrollmentId}

Reads bounded execution history including chosen branches and safe stop reasons.

MCP toolget_sequence_participantKeyaudience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The resource ID in the authenticated account

enrollmentIdrequired

path · string

The resource ID in the authenticated account

Request
curl "http://localhost:3000/api/v1/sequences/6650f1c2e9b1d4a012345678/participants/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Change participant state

POST/api/v1/sequences/{id}/participants/{enrollmentId}/lifecycle

Pauses, resumes or stops one enrollment without reentry or replaying an unknown provider attempt.

MCP toolsequence_participant_lifecycleKeyaudience:write + audience:readSafe to repeat
Parameter
idrequired

path · string

The resource ID in the authenticated account

enrollmentIdrequired

path · string

The resource ID in the authenticated account

requestIdrequired

body · string

A stable UUID for this exact operation; reuse it only to retry the same payload

expectedCursorVersionrequired

body · integer

The expected version returned by the latest read of this resource

actionrequired

body · "pause" | "resume" | "stop"

The participant lifecycle transition; unknown outcomes cannot resume

Request
curl -X POST "http://localhost:3000/api/v1/sequences/6650f1c2e9b1d4a012345678/participants/6650f1c2e9b1d4a012345678/lifecycle" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"requestId":"…","expectedCursorVersion":"…","action":"…"}'

Groups

On v2 every group belongs to one newsletter: list/create require newsletterId, and membership uses an existing Subscriber in that newsletter. Membership never grants consent. V1 account-wide groups remain available during maintenance.

List groups

GET/api/v1/groups

Lists organizational groups and member counts. On v2 newsletterId is required and only groups of that newsletter are returned. Membership does not grant permission to send email.

MCP toollist_groupsKeycontent:readRead-onlySafe to repeat
Parameter
newsletterId

query · string

The owning newsletter ID; required for v2 group listing and creation

archived

query · boolean

List archived groups instead of active groups

query

query · string

Case-insensitive literal text in the group name

page

query · integer

Page number, starting at 1; 50 results per page

Request
curl "http://localhost:3000/api/v1/groups" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Get a group

GET/api/v1/groups/{id}

Reads one organizational group, including an archived group. On v2 the DTO includes its immutable newsletterId.

MCP toolget_groupKeycontent:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The group's ID

Request
curl "http://localhost:3000/api/v1/groups/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Create a group

POST/api/v1/groups

Creates an empty organizational group. On v2 newsletterId is required and cannot later change. Does not create contacts, consent or email.

MCP toolcreate_groupKeyaudience:write
Parameter
namerequired

body · string

The group name, 1 to 100 characters

newsletterId

body · string

The owning newsletter ID; required for v2 group listing and creation

Request
curl -X POST "http://localhost:3000/api/v1/groups" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"…"}'

Rename a group

PATCH/api/v1/groups/{id}

Renames an active group without changing its v2 newsletter parent, membership or consent.

MCP toolupdate_groupKeyaudience:writeSafe to repeat
Parameter
idrequired

path · string

The group's ID

namerequired

body · string

The group name, 1 to 100 characters

Request
curl -X PATCH "http://localhost:3000/api/v1/groups/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"…"}'

Archive a group

DELETE/api/v1/groups/{id}

Archives a group and retains its newsletter-specific members. Does not unsubscribe contacts or change campaigns.

MCP toolarchive_groupKeyaudience:writeSafe to repeat
Parameter
idrequired

path · string

The group's ID

Request
curl -X DELETE "http://localhost:3000/api/v1/groups/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

List group members

GET/api/v1/groups/{id}/members

Lists group members, including unsubscribed contacts. On v2 each row has subscriberId instead of email and is scoped to the group's newsletter. This is not an eligible sending audience.

MCP toollist_group_membersKeyaudience:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The group's ID

page

query · integer

Page number, starting at 1; 50 results per page

Request
curl "http://localhost:3000/api/v1/groups/6650f1c2e9b1d4a012345678/members" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Add a group member

POST/api/v1/groups/{id}/members

Adds an existing profile to a group once, without changing consent or sending email. On v2 pass subscriberId (or a legacy email alias); the group determines its newsletter.

MCP tooladd_group_memberKeyaudience:write + audience:read + messages:sendSafe to repeat
Parameter
idrequired

path · string

The group's ID

email

body · string

An existing contact email in this account; membership never grants consent

subscriberId

body · string

The v2 canonical subscriber ID; membership never grants consent

Request
curl -X POST "http://localhost:3000/api/v1/groups/6650f1c2e9b1d4a012345678/members" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Remove a group member

POST/api/v1/groups/{id}/members/remove

Removes a profile from this newsletter's group without unsubscribing it. On v2 pass subscriberId or a legacy email alias.

MCP toolremove_group_memberKeyaudience:write + audience:readSafe to repeat
Parameter
idrequired

path · string

The group's ID

email

body · string

An existing contact email in this account; membership never grants consent

subscriberId

body · string

The v2 canonical subscriber ID; membership never grants consent

Request
curl -X POST "http://localhost:3000/api/v1/groups/6650f1c2e9b1d4a012345678/members/remove" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Signup forms

List signup forms

GET/api/v1/forms

Lists private form drafts and immutable publication summaries, without subscriber data.

MCP toollist_formsKeycontent:readRead-onlySafe to repeat
Parameter
status

query · "draft" | "published" | "archived"

Only forms with this status

newsletterId

query · string

Limit forms to their owning newsletter

page

query · integer

Page number, starting at 1; 50 results per page

Request
curl "http://localhost:3000/api/v1/forms" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Get a signup form

GET/api/v1/forms/{id}

Reads a private draft, its current published revision and publication readiness.

MCP toolget_formKeycontent:readRead-onlySafe to repeat
Parameter
idrequired

path · string

The signup form's ID

Request
curl "http://localhost:3000/api/v1/forms/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Create a signup form

POST/api/v1/forms

Creates an inert private draft. Does not subscribe anyone or send email.

MCP toolcreate_formKeycontent:write
Parameter
namerequired

body · string

Private form name, 1 to 100 characters

draft

body · object

Optional initial publication fields; incomplete drafts are allowed

draft.title

body · string

Public form title; required before publication

draft.consentText

body · string

Exact plain-text consent wording approved by the operator

draft.privacyUrl

body · string

Real privacy policy URL; no fragments or credentials

draft.groupId

body · string

A group belonging to this account and, on v2 accounts, the selected newsletter

draft.newsletterId

body · string

The newsletter joined after double opt-in

draft.allowedOrigins

body · string[]

Exact HTTPS origins permitted to embed this form; maximum 20

Request
curl -X POST "http://localhost:3000/api/v1/forms" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"…"}'

Edit a signup form

PATCH/api/v1/forms/{id}

Updates private draft fields using editVersion. An existing public revision remains unchanged.

MCP toolupdate_formKeycontent:write
Parameter
idrequired

path · string

The signup form's ID

expectedVersionrequired

body · integer

The editVersion returned by the last read; prevents overwriting concurrent edits

name

body · string

Private form name, 1 to 100 characters

draft

body · object

Merge these fields into the existing private draft

draft.title

body · string

Public form title; required before publication

draft.consentText

body · string

Exact plain-text consent wording approved by the operator

draft.privacyUrl

body · string

Real privacy policy URL; no fragments or credentials

draft.groupId

body · string

A group belonging to this account and, on v2 accounts, the selected newsletter

draft.newsletterId

body · string

The newsletter joined after double opt-in

draft.allowedOrigins

body · string[]

Exact HTTPS origins permitted to embed this form; maximum 20

Request
curl -X PATCH "http://localhost:3000/api/v1/forms/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"expectedVersion":"…"}'

Publish a signup form

POST/api/v1/forms/{id}/publish

Publishes an immutable revision only after audience, delivery, sender and source readiness checks pass. Does not send email.

MCP toolpublish_formKeysettings:manage + messages:sendSafe to repeat
Parameter
idrequired

path · string

The signup form's ID

expectedVersionrequired

body · integer

The editVersion returned by the last read; prevents overwriting concurrent edits

Request
curl -X POST "http://localhost:3000/api/v1/forms/6650f1c2e9b1d4a012345678/publish" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"expectedVersion":"…"}'

Archive a signup form

DELETE/api/v1/forms/{id}

Stops new signup requests and pending confirmations for this form. Existing consent and memberships remain unchanged.

MCP toolarchive_formKeysettings:manageSafe to repeat
Parameter
idrequired

path · string

The signup form's ID

Request
curl -X DELETE "http://localhost:3000/api/v1/forms/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Domains

Own sending domains with their DNS records, and the shared address.

List domains

GET/api/v1/domains

Lists the account's own sending domains with their DNS records and status as last checked, and each newsletter's shared address (hello@<slug>.<shared domain>), which works with no setup.

MCP toollist_domainsKeycontent:readRead-onlySafe to repeat
Request
curl "http://localhost:3000/api/v1/domains" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Add a domain

POST/api/v1/domains

Adds a domain to send from, in the account's own tenant at the email provider: emails are signed with DKIM and bounces return to a subdomain of it (rp.<domain> on PostShiba, bounce.<domain> on Amazon SES). The answer lists the DNS records to add; check_domain reads them once they're in. Newsletters can send from it once it's verified.

MCP tooladd_domainKeysettings:manage + messages:sendReaches outside ApresMail
Parameter
domainrequired

body · string

e.g. example.com. An address or a link works too: jane@example.com and https://www.example.com/about both add example.com.

archiveHost

body · string

Used when the domain's setup lists an archive step: the subdomain for the archive, tracked links and unsubscribe links. Default: news.<domain>.

Request
curl -X POST "http://localhost:3000/api/v1/domains" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"example.com"}'

Retry a domain's sender setup and check its DNS records

POST/api/v1/domains/{id}/check

Retries incomplete sender setup, then asks the email provider and DNS again whether the domain's records are in, and looks up its DMARC record or its parent domain's. On PostShiba, a check within a minute of the last one answers what that one found. When its setup lists an archive step, the newsletter sending from the domain moves its archive and links to that subdomain once it points at ApresMail.

MCP toolcheck_domainKeysettings:manage + messages:sendSafe to repeatReaches outside ApresMail
Parameter
idrequired

path · string

The domain's ID

Request
curl -X POST "http://localhost:3000/api/v1/domains/6650f1c2e9b1d4a012345678/check" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Remove a domain

DELETE/api/v1/domains/{id}

Removes a domain from the email provider, and its archive subdomain from ApresMail when its setup lists one. Newsletters on it can't send until they move to another address. Refused while a campaign from it is sending, paused or scheduled. Adding it again needs new DNS records.

MCP toolremove_domainKeysettings:manage + messages:sendCan't be undoneSafe to repeatReaches outside ApresMail
Parameter
idrequired

path · string

The domain's ID

Request
curl -X DELETE "http://localhost:3000/api/v1/domains/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Images

Pictures for campaign content, on ApresMail's CDN, kept in the account's library to use again.

List images

GET/api/v1/images

Lists the images uploaded to the account, newest first, 50 a page, so a campaign can use one again without uploading it twice. Pass nextCursor back as cursor for the next page.

MCP toollist_imagesKeycontent:readRead-onlySafe to repeat
Parameter
limit

query · integer

Images per page, 50 by default, 100 at most

cursor

query · string

nextCursor from the previous page

Request
curl "http://localhost:3000/api/v1/images?limit=20" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Upload an image

POST/api/v1/images

Stores a PNG, JPEG, GIF or WebP image under 4 MB on ApresMail's CDN and returns its URL for campaign content. Send the file as base64 (under about 3 MB, since requests stop at 4.5 MB) or an https:// link ApresMail downloads. The URL never changes: sent emails keep pointing at it. list_images finds images uploaded before.

MCP toolupload_imageKeycontent:writeReaches outside ApresMail
Parameter
base64

body · string

The image file, base64 encoded; a data: URL works too

url

body · string

An https:// link to the image

fileName

body · string

Used in the stored file's name

contentType

body · string

The file's type, checked against its first bytes

Request
curl -X POST "http://localhost:3000/api/v1/images" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/cover.png"}'

API keys

Keys for the REST API and MCP.

List API keys

GET/api/v1/api-keys

Lists the account's API keys, revoked ones included, with their level and when they were last used. Keys themselves are never shown again.

MCP toollist_api_keysKeyDashboard or legacy full credentials onlyRead-onlySafe to repeat
Request
curl "http://localhost:3000/api/v1/api-keys" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Create an API key

POST/api/v1/api-keys

Creates an API key and returns it once; only its hash is stored. Scoped keys have selected permissions and expire after 7, 30 or 90 days. Only dashboard sessions or legacy full credentials can manage keys. Legacy full/signups modes remain for compatibility. An account has up to 20 active keys: one more answers conflict until one is revoked.

MCP toolcreate_api_keyKeyDashboard or legacy full credentials only
Parameter
namerequired

body · string

What the key is for, e.g. Website signups

level

body · "full" | "signups" | "scoped"

scoped for selected permissions; full/signups preserve legacy integrations

scopes

body · "content:read" | "content:write" | "messages:send" | "audience:read" | "audience:write" | "settings:manage"[]

Explicit independent permissions; required for scoped keys

expiresInDays

body · number

Scoped key lifetime: 7, 30 or 90 days; default 30

Request
curl -X POST "http://localhost:3000/api/v1/api-keys" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Draft assistant","level":"scoped","scopes":["content:read","content:write"],"expiresInDays":30}'

Revoke an API key

DELETE/api/v1/api-keys/{id}

Revokes an API key for good: requests with it answer unauthorized from now on. A key can revoke itself.

MCP toolrevoke_api_keyKeyDashboard or legacy full credentials onlyCan't be undoneSafe to repeat
Parameter
idrequired

path · string

The API key's ID

Request
curl -X DELETE "http://localhost:3000/api/v1/api-keys/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

List connected apps

GET/api/v1/connected-apps

Lists the apps connected to the account with OAuth, such as ChatGPT, Claude and Grok Bot, with when they were connected and last used. Each app has its selected permissions; older connections may retain legacy full access.

MCP toollist_connected_appsKeyDashboard or legacy full credentials onlyRead-onlySafe to repeat
Request
curl "http://localhost:3000/api/v1/connected-apps" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"

Disconnect an app

DELETE/api/v1/connected-apps/{id}

Disconnects an app connected with OAuth: its tokens stop working at once, and it has to ask for access again to come back. An app can disconnect itself.

MCP toolrevoke_connected_appKeyDashboard or legacy full credentials onlyCan't be undoneSafe to repeat
Parameter
idrequired

path · string

The connected app's ID

Request
curl -X DELETE "http://localhost:3000/api/v1/connected-apps/6650f1c2e9b1d4a012345678" \
  -H "Authorization: Bearer $APRESMAIL_API_KEY"