Guides

Authentication

Every request carries an API key as a bearer token. The key decides the account, and its permissions decide what it can do. ChatGPT and Claude don't need one: they connect to the MCP server with OAuth.

Send the key

Create keys on the dashboard's API keys page. They start with mc_ and are shown once: ApresMail only keeps their hash, their first characters and when they were last used. The REST API and the MCP server take the same header. An account has up to 20 active keys.

Header
Authorization: Bearer mc_…

Selected permissions and legacy keys

New keys default to reading and editing drafts and expire after 30 days; choose 7, 30 or 90 days. Sending and subscriber access start disabled. Scoped credentials cannot create keys or manage connected apps.

  • content:read: Read drafts, newsletter content and aggregate results.
  • content:write: Work on drafts and media. Pause or cancel campaigns.
  • messages:send: Send tests, approve or schedule campaigns, resume sequences and enable sending flows.
  • audience:read: Read people, contact exports, memberships and individual activity.
  • audience:write: Change subscribers, imports and memberships. Operations returning personal data also need read access.
  • settings:manage: Manage newsletter settings, sending domains, forms and archives. Live sending settings also need send access.
LevelCan
Legacy full accessEvery endpoint and MCP tool, including creating and revoking keys. Keep it on a server or in your AI assistant's settings.
Legacy signups onlyOnly (POST /api/v1/contacts), for signup forms. It can go in a web page: that endpoint answers browsers, and the key can't read or send anything.

A signups only key calling anything else gets 403 forbidden. Keys made before levels existed are signups only. Expired or revoked keys get 401 unauthorized. A scoped key missing a required permission gets 403 forbidden. Tests, scheduling, sequence activation/resumption and other delivery-capable operations require sending permission.

A signup form

With a signups only key, from the browser. Pass the visitor's IP from a server to limit signups per visitor.

JavaScript
await fetch("http://localhost:3000/api/v1/contacts", {
  method: "POST",
  headers: {
    Authorization: "Bearer mc_your_signups_only_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ email: form.email.value, source: "website" }),
});

Rate limits

Each key gets 300 requests a minute across REST and MCP. Some actions have their own limit, for each key and for the account: its keys, connected apps and dashboard share the account's, so more keys don't raise it. Over a limit the answer is 429 rate_limited; wait and retry.

add_contact600 an hour, 5 per visitor in 10 minutes
update_newsletter3 slug changes a day per account
list_native_campaigns60 an hour
validate_native_countdown60 an hour
check_newsletter_slug300 an hour
send_welcome_test_email20 an hour
create_campaign60 an hour
duplicate_campaign60 an hour
send_test_email30 an hour
schedule_campaign30 an hour
send_campaign30 an hour
resume_campaign30 an hour
preview_campaign_cleanup30 an hour
prepare_campaign_review30 an hour
approve_campaign_review30 an hour
inspect_import_recipients120 a minute
create_subscriber_import30 a minute
upload_subscriber_import_chunk30 a minute
stage_subscriber_import30 a minute
preview_subscriber_import30 a minute
get_subscriber_import120 a minute
list_subscriber_imports120 a minute
get_subscriber_import_rows120 a minute
approve_subscriber_import30 a minute
apply_subscriber_import30 a minute
cancel_subscriber_import30 a minute
export_subscriber_import_report120 a minute
delete_contact120 an hour
import_contacts120 an hour
export_contacts30 an hour
count_segment600 an hour
create_segment60 an hour
add_domain10 an hour
check_domain60 an hour
upload_image60 an hour
create_api_key10 an hour

Access and limits

Production sending requires an active Apresly subscription. Account limits are assigned individually by an administrator and apply equally to the dashboard, API and MCP.