Email marketing platform Polaris Software-owned since the 2019 Hatchbuck merger; nine languages
Benchmark Email logo

Benchmark Email API + MCP (2026): drafts yes, sending no

Benchmark Email ships a modern REST API-Benchmark Email API v1.0.0, launched April 2026 at developers.benchmarkemail.io, with scoped X-API-Key auth, an OpenAPI spec and per-account regional base URLs. What it does not ship is a way to send: campaigns can be created, configured and duplicated over the API, but scheduling, sending and test-sending are web-app only, and no SMTP relay or transactional endpoint exists at any plan tier.

On the agent side there is no official MCP server as of August 2026-only third-party access via Zapier or Composio. The ceiling here is structural, not a pricing gate.

At a glance

v1.0.0
Current REST API
April 2026 · supersedes “RESTful API v3.0”
0
Official SDKs for v1.0.0
5 legacy XML-RPC wrappers · OpenAPI spec only
None
Official MCP server
2 third-party options · neither can make it send

MCP integration in 2026

Model Context Protocol gives an AI assistant a typed tool interface instead of guessing at HTTP calls. For an ESP the real question is not whether an agent can read your lists, any wrapper does that, but whether it can close the loop and send. For Benchmark the answer is no, and no MCP server can change it.

i

No official MCP server, third-party wrappers only

As of August 19, 2026 Benchmark publishes no first-party MCP server. Its GitHub organisation holds 7 public repositories, all legacy XML-RPC wrappers, and the April 2026 API launch never mentioned MCP. Access runs through Zapier MCP or the commercial Composio toolkit, both inherit the same ceiling: an agent drafts, a human presses send.

Available MCP servers

Two production-usable options, both authenticating with your own key, so their traffic spends your budget.

Why buyers should care

If your criterion is “can my agent run the newsletter end to end”, Benchmark fails structurally, and no MCP announcement fixes that without an API change first. It is agent-assistable, not agent-operable: an assistant enriches contacts, segments lists, drafts a campaign and pulls reports, then hands you the draft. If you need agents that actually send, evaluate Mailchimp or MailerLite, whose APIs expose send and schedule operations an MCP layer can wrap. Benchmark does publish an agent-readable SKILL.md manifest and an llms.txt index, documentation for a model, not a server your client can connect to.

Benchmark Email API essentials

The current API is documented at developers.benchmarkemail.io with an OpenAPI document at /openapi.json. The detail that trips up most first integrations: the base URL is not global. Each account is pinned to a region and cluster, so hardcoding the docs example ships a client that 401s everywhere else.

Base URLhttps://api-{region}-{cluster}.benchmarkemail.io-per account
Docs example hostapi-us-west-2-a.benchmarkemail.io-regions us · eu · jp
Versionv1.0.0 CURRENT
Legacy base URLclientapi.benchmarkemail.com-v3.0, deprecated, still live
Auth headerX-API-Key: bme_{region}_{43 chars}50 chars
PaginationInconsistent, body params, query params, or none, by endpoint
Error shape{"errors":[{"errorType","message","field"}]}
Budget headersX-RateLimit-* and X-Monthly-* on every response
Send / scheduleNot available via API, web application only
SMTP relayDoes not exist at any plan tier

The resource model is narrow and marketing-shaped: contacts, contact structures (the container defining your custom-field schema), lists, campaigns, templates, domains, reports. Note the hierarchy, lists are not top-level, they live at /api/contact-structure/{id}/lists, so most list work starts by resolving a structure id. GET /api/contact-structure is therefore the smoke test for a new key: cheap, read-scope, and it confirms base URL and region at once.

Authentication methods

Three schemes are live at once because three APIs are. Only the first applies to anything you should build in 2026.

X-API-Key (current API v1.0.0)

Keys are created by the account owner only, at Settings › API Keys, and displayed exactly once, a lost key means issuing a new one. The format is bme_{2-letter region}_{43 random chars}, 50 characters; the embedded region is a handy check that you are calling the matching host. There is no OAuth flow and no bearer variant.

Keys carry per-resource scopes-contacts, campaigns, reports, domains, each :read or :write, with write implying read. Active keys are capped at 2 on Free and 10 on Pro.

Scoping buys blast-radius control, not throughput

One key per integration is right for auditing and revocation, but it does not partition the rate limit. The 3,600 requests/hour ceiling is enforced per account across every key, so ten keys split one budget ten ways. Size polling intervals against the account total.

AuthToken (legacy RESTful API v3.0)

The deprecated v3.0 API at clientapi.benchmarkemail.com uses an AuthToken header carrying an admin token from ui.benchmarkemail.com/Integrate#AP. It is unscoped and account-wide, still works, has no published sunset date, and outranks the current docs in search, which is why so many 2026 integrations get built against it by accident.

Token methods (legacy XML-RPC v1.0)

The oldest surface, at apidocs.benchmarkemail.com, uses XML-RPC with token-based security methods. Every SDK in the BenchmarkEmail GitHub org targets it. Treat anything mentioning XML-RPC as archaeology, not a starting point.

Rate limits

Two independent ceilings stack, and both return the same status code, so the response alone will not tell you which wall you hit.

LimitValueScope
Hourly ceiling3,600 req/hourPer account, shared across all keys
Sustained rate60 req/minuteRoughly 1 req/second
Monthly quota (Free)contacts × 10500 contacts = 5,000 calls/month
Monthly quota (paid)contacts × 1005,000 contacts = 500,000 calls/month
Active API keys2 Free · 10 ProOwner-created only
Legacy v3.0 ceiling500 / 2 min · 60,000/dayDifferent API, do not mix the sets
Platform send rate~20,000/hour~25,000/hour with a paid dedicated IP

Breaching either limit returns HTTP 429 with errorType: TooManyRequestsError and a Retry-After header in seconds; the same 429 also signals IP-level blocks, which expire on their own. The workaround is budget-aware batching, not backoff tuning: retry only on 429, seeding backoff from Retry-After-a 401 or 403 is a config error that retrying just burns quota on. Drive contact sync through POST /api/contact/search at pageSize 50 so 50,000 contacts cost 1,000 calls, and check X-Monthly-Remaining before a full resync.

Official SDKs

The weakest part of the developer story: there is no official SDK for the current API. The five wrappers in the BenchmarkEmail GitHub org all describe themselves as XML-RPC clients for the legacy v1.0 API and predate the 2026 rewrite by years. They are listed so you can avoid them.

LanguagePackageInstallRepo
PHPbenchmarkemail-php-API-wrappergit clone-XML-RPCGitHub
Javabenchmarkemail-java-API-wrappergit clone-XML-RPCGitHub
Javabmejavawrappergit clone-near-duplicateGitHub
C# / .NETbenchmarkemail-.NET-cSharp-API-wrappergit clone-XML-RPCGitHub
Rubybmerubywrappergit clone-XML-RPCGitHub
Any (v1.0.0)none publishedGenerate from /openapi.jsonAPI reference

Every published SDK targets a deprecated API

All 5 first-party wrappers are XML-RPC clients for the oldest Benchmark API. None speaks X-API-Key, none knows the regional hosts, none parses the current {"errors":[...]} envelope, and two near-identical Java repos is itself a maintenance signal. Generate a client from the OpenAPI document instead.

Notable community SDKs

There is no real community ecosystem either, unsurprising for an API four months old with no send capability to build on. The closest substitutes are workflow clients: the certified Power Automate connector and the community n8n node. Neither gives you typed models in your own codebase; for that, openapi-generator against /openapi.json emits a serviceable client in one command.

Endpoints reference

The full surface is in the official API reference; prefix every path with your base URL. Note what is absent: no /send, no /schedule, no /transactional, no webhooks.

ResourceMethodsDescription
Contacts
/api/contact
GET, POSTList all contacts (unpaginated) or create one.
Contacts
/api/contact/{id}
GET, PUT, PATCH, DELETERead, replace, update or delete one contact.
Contacts
/api/contact/search
POSTPaginated, filtered search, use on large databases.
Contacts
/api/contact/export
POSTBulk export contacts out of the account.
Contacts
/api/contact/{id}/events
GETOpens, clicks and bounces for one contact.
Contacts
/api/contact/events
GETAccount-wide contact events across all contacts.
Contact structure
/api/contact-structure
GET, POSTList or create structures; smoke test for a key.
Contact structure
/api/contact-structure/{id}
GET, PUTRead or update a structure and its custom fields.
Lists
/api/contact-structure/{id}/lists
GET, POST, DELETEList, create, or bulk-delete lists under a structure.
Lists
/api/contact-structure/{id}/lists/{listId}
GET, PATCH, DELETESingle-list read, update, delete; duplicate alongside.
Campaigns
/api/email/campaign
GET, POSTList with ?page=&size=, or create a draft.
Campaigns
/api/email/campaign/{id}
GET, PATCH, DELETERead, update sender/subject/body/lists, delete.
Campaigns
/api/email/campaign/{id}/duplicate
POSTClone an existing campaign into a new draft.
Templates
/api/email/template
GETBrowse templates and categories, or fetch one by id.
Domains
/api/email/domain
GETSending domains and auth status; needs domains:read.

Reporting sits at /api/reports/dashboard, /api/reports/email/{campaignId} and a sibling /engagement path. Duplication is the closest thing to a templating workflow: clone a known-good campaign, PATCH subject and lists, hand the draft over.

Code examples

Python, paginated contact sync and a budget probe

Never call GET /api/contact against a real database; page through POST /api/contact/search, retry only on 429, and read the budget headers before a full resync.

import os, requests

# NOT a global endpoint - read yours from Settings > API Keys.
BASE = os.environ["BENCHMARK_API_BASE_URL"].rstrip("/")
s = requests.Session()
s.headers.update({"X-API-Key": os.environ["BENCHMARK_API_KEY"],
                  "Content-Type": "application/json"})

def search(page=1, page_size=50):
    """GET /api/contact returns EVERY contact unpaginated. Use this."""
    r = s.post(f"{BASE}/api/contact/search",
               json={"page": page, "pageSize": page_size}, timeout=30)
    if r.status_code == 429:                     # retry ONLY on 429
        raise RuntimeError(f"retry in {r.headers.get('Retry-After', 60)}s")
    r.raise_for_status()
    return r.json()

def iter_contacts(page_size=50):
    first = search(1, page_size)
    yield from first["contacts"]
    pages = -(-first["totalRecords"] // page_size)   # ceil division
    for p in range(2, pages + 1):
        yield from search(p, page_size)["contacts"]

probe = s.get(f"{BASE}/api/contact-structure", timeout=30)
print("monthly budget left:", probe.headers["X-Monthly-Remaining"])

Node.js, both pagination conventions

One client covering contacts and campaigns, plus a draft. Note where the pipeline stops.

// Benchmark Email API v1.0.0 - Node 18+
const BASE = process.env.BENCHMARK_API_BASE_URL.replace(/\/$/, '');
const headers = { 'X-API-Key': process.env.BENCHMARK_API_KEY,
                  'Content-Type': 'application/json' };

async function call(path, options = {}) {
  const res = await fetch(`${BASE}${path}`, { ...options, headers });
  if (res.status === 429)              // retry ONLY on 429
    throw new Error(`retry in ${res.headers.get('Retry-After') ?? 60}s`);
  if (!res.ok) throw new Error(`${res.status}`);  // {errors:[{errorType}]}
  return res.json();
}

// Contacts: page/pageSize go in the BODY...
const searchContacts = (page = 1, pageSize = 50) =>
  call('/api/contact/search',
       { method: 'POST', body: JSON.stringify({ page, pageSize }) });

// ...campaigns use the QUERY STRING and rename pageSize to `size`.
const listCampaigns = (page = 1, size = 25) =>
  call(`/api/email/campaign?page=${page}&size=${size}`);

// Create a DRAFT. Only `name` is required. Pipeline stops here:
// no send, no schedule, no webhook.
const draft = await call('/api/email/campaign',
  { method: 'POST', body: JSON.stringify({ name: 'August Update' }) });

Common gotchas

The API can build a campaign but can never send it

The official guide is blunt: “scheduling, sending, canceling, and test-sending campaigns is not available via API key”. You can POST /api/email/campaign, set sender, subject, body and lists, then the pipeline stops dead and a human presses send. No webhook, no queue, no plan tier unlocks it, and there is no SMTP relay either: build in a manual approval gate, or pick another ESP.

The higher version number is the older API

Current: API v1.0.0 at developers.benchmarkemail.io, April 2026, X-API-Key with bme_ keys. Deprecated: RESTful API v3.0 at clientapi.benchmarkemail.com with an AuthToken header. Oldest: XML-RPC v1.0. All three are live and indexed, and v3 outranks v1.0.0 in search because it is older and better linked. Their rate limits differ, so the wrong doc breaks your backoff. The same split runs through the product itself: the rebuilt platform of October 2025 and “Benchmark Email Classic” have separate logins, separate Zapier apps and diverging knowledge bases, and only the new platform is served by API v1.0.0.

Rate limits are per account, and two of them stack

The 3,600 requests/hour ceiling is shared across every key, so one key per integration splits the budget rather than multiplying it. On top sits a monthly quota of contacts × 10 on Free and × 100 on paid: a 500-contact Free account gets 5,000 calls a month, which one naive sync exhausts. Both breaches return 429, watch X-RateLimit-Remaining and X-Monthly-Remaining to know which wall you hit.

Pagination is inconsistent, and one endpoint has none

GET /api/contact returns every matching contact in one unpaginated array; nothing stops you firing it at 50,000 contacts. POST /api/contact/search wants page and pageSize in the JSON body. GET /api/email/campaign wants them in the query string and renames the parameter to size. Three conventions in one API, code written against the contacts pattern silently returns only page one of campaigns.

Deprecations and changelog

  • April 1, 2026-REST API v1.0.0 launched: scoped X-API-Key auth, OpenAPI spec, regional base URLs, key caps of 2 Free / 10 Pro. Supersedes RESTful API v3.0, with no sunset date published for it.
  • April 1, 2026-Domain authentication gained DNS copy warnings, extended retry timing and clearer record viewing; send failures now give a specific reason instead of a generic “Failed”.
  • April 1, 2026-Annual billing introduced at roughly 15% saving versus monthly; user billing now charges on peak concurrent users with prorated adjustment.
  • October 6, 2025-Rebuilt platform launched with a new brand identity. “Benchmark Email Classic” stays on a separate login with no announced sunset, the two-product split that still causes documentation confusion.
  • June 17, 2025-“What’s New at Benchmark: June 2025” release notes published, the last KB note located before the API rewrite.

Changelog content is split across product updates, the KB release notes and the Help Scout centre, and none is complete, product-updates surfaces nothing newer than Q1 2025.

Frequently asked questions

What is the current Benchmark Email API version and base URL?

The current API is Benchmark Email API v1.0.0 at developers.benchmarkemail.io, launched April 2026. There is no global host: the base URL is https://api-{region}-{cluster}.benchmarkemail.io, unique to your account. Regions us, eu and jp appear in official docs; copy your own host from Settings › API Keys.

How do I get a Benchmark Email API key and what scopes are available?

Only the account owner can create keys, at Settings › API Keys, and a key is shown once at creation with no retrieval path afterwards. Format is bme_{region}_{43 chars}, 50 characters, sent in the X-API-Key header. Scopes cover contacts, campaigns, reports and domains, read or write, with write implying read. Free holds 2 keys, Pro up to 10.

What are the Benchmark Email API rate limits?

Two stacked limits. Hourly: 3,600 requests per hour per account, about 60 per minute, shared across every key, extra keys buy no throughput. Monthly: contact limit × 10 on Free and × 100 on paid, so 5,000 contacts on Pro gives 500,000 calls a month, a 500-contact Free account just 5,000. Both return 429 with Retry-After.

Can I send an email campaign with the Benchmark Email API?

No. You can create a draft with POST /api/email/campaign, configure sender, subject, body and lists with PATCH, and duplicate campaigns, but the official guide states that scheduling, sending, canceling and test-sending are not available via API key and must happen in the web app. No plan tier unlocks it, and there is no SMTP relay either.

Is the Benchmark Email RESTful API v3 deprecated?

Yes, despite the higher version number. RESTful API v3.0 on clientapi.benchmarkemail.com, with its AuthToken header, is the older generation, superseded by API v1.0.0 in April 2026; an older XML-RPC v1.0 sits behind it. All three remain live, with no sunset date published for the legacy pair. Confirm the hostname, not the version string, before trusting a tutorial.

Is there an official Benchmark Email MCP server for AI agents?

No. As of August 2026 there is no first-party MCP server, nothing on the BenchmarkEmail GitHub org, nothing at developers.benchmarkemail.io, no mention in the April 2026 API launch. Third-party access exists via Zapier MCP and the commercial Composio toolkit. No MCP server can make Benchmark send, because the API exposes no send operation to wrap.

Changelog (recent)

  • 2026-04-01 REST API v1.0.0 launched at developers.benchmarkemail.io with scoped X-API-Key auth, an OpenAPI spec and regional base URLs; supersedes the legacy RESTful API v3.0 on clientapi.benchmarkemail.com.
  • 2026-04-01 Domain authentication gained DNS copy warnings, extended retry timing and clearer record viewing; send-failure messages now give a specific reason and suggested next steps.
  • 2026-04-01 Annual billing introduced (~15% saving vs monthly) alongside user billing charged on peak concurrent users with prorated adjustment.
AAlaa Touil RRabeb How we test →

This review follows our email infrastructure testing methodology. We disclose affiliate relationships in our editorial independence policy.