Guides
Authentication
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.
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.
| Level | Can |
|---|---|
| Legacy full access | Every endpoint and MCP tool, including creating and revoking keys. Keep it on a server or in your AI assistant's settings. |
| Legacy signups only | Only (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.
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_contact | 600 an hour, 5 per visitor in 10 minutes |
| update_newsletter | 3 slug changes a day per account |
| list_native_campaigns | 60 an hour |
| validate_native_countdown | 60 an hour |
| check_newsletter_slug | 300 an hour |
| send_welcome_test_email | 20 an hour |
| create_campaign | 60 an hour |
| duplicate_campaign | 60 an hour |
| send_test_email | 30 an hour |
| schedule_campaign | 30 an hour |
| send_campaign | 30 an hour |
| resume_campaign | 30 an hour |
| preview_campaign_cleanup | 30 an hour |
| prepare_campaign_review | 30 an hour |
| approve_campaign_review | 30 an hour |
| inspect_import_recipients | 120 a minute |
| create_subscriber_import | 30 a minute |
| upload_subscriber_import_chunk | 30 a minute |
| stage_subscriber_import | 30 a minute |
| preview_subscriber_import | 30 a minute |
| get_subscriber_import | 120 a minute |
| list_subscriber_imports | 120 a minute |
| get_subscriber_import_rows | 120 a minute |
| approve_subscriber_import | 30 a minute |
| apply_subscriber_import | 30 a minute |
| cancel_subscriber_import | 30 a minute |
| export_subscriber_import_report | 120 a minute |
| delete_contact | 120 an hour |
| import_contacts | 120 an hour |
| export_contacts | 30 an hour |
| count_segment | 600 an hour |
| create_segment | 60 an hour |
| add_domain | 10 an hour |
| check_domain | 60 an hour |
| upload_image | 60 an hour |
| create_api_key | 10 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.