Guides
Authentication
Send the key
Create keys on the dashboard's API keys page. They start with mc_ and are shown once: iCharles Mail 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_…Two levels
| Level | Can |
|---|---|
| Full access | Every endpoint and MCP tool, including creating and revoking keys. Keep it on a server or in your AI assistant's settings. |
| Signups only | Only add_contact (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. Revoked keys get 401 unauthorized.
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("https://newsletters.icharles.com/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 |
| 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 |
| send_campaign_to_more | 30 an hour |
| resume_campaign | 30 an hour |
| preview_campaign_cleanup | 30 an hour |
| delete_contact | 120 an hour |
| import_contacts | 120 an hour |
| export_contacts | 30 an hour |
| add_domain | 10 an hour |
| check_domain | 60 an hour |
| upload_image | 60 an hour |
| create_api_key | 10 an hour |
| change_plan | 30 an hour |
| open_billing_portal | 30 an hour |
Plans
Everything but the billing endpoints needs an active plan; without one the answer is 402 subscription_required. Signups and confirmation emails keep coming in over the plan's limits. Campaign sends stop with plan_limit_emails or plan_limit_subscribers. Welcome emails count toward the month's emails like issues: once they're used up, new subscribers get none until the count starts over or the plan grows, and don't get one later. usage.welcomeEmailsPaused in get_billing and get_overview says so.