Email marketing platform Constant Contact-owned since June 2025; white-labels as Sitecore Send
Moosend logo

Moosend API + MCP (2026): v3 REST, no official MCP server

Last verified Aug 27, 2026

Moosend exposes a single REST API-v3, at https://api.moosend.com/v3-covering subscribers, lists, segments, campaigns, reporting and transactional sends. It works, and it is visibly dated: auth is an apikey query-string parameter, response format is chosen by a .json or .xml extension on the path, and pagination uses path segments. On the agent side the verdict is blunt: as of August 2026 there is no official Moosend MCP server, and no dedicated community one either.

That shapes how you build. The API is simple enough that a plain HTTP client beats every official SDK, all nine of which are abandoned, but the developer surface has not moved in years, so treat Moosend as a marketing back end you script against, not a platform you expect to grow with you. For relay configuration, see SMTP settings.

At a glance

v3
REST API version
api.moosend.com/v3 · JSON or XML by extension

9
Official SDKs
All unmaintained · 8 frozen since 2017

None
Official MCP server
Indirect via Zapier, Pipedream or Make

MCP integration in 2026

Model Context Protocol gives an AI agent typed, permissioned access to a platform without a hand-rolled wrapper, for an ESP, an assistant adding a subscriber or triggering an automation as a first-class tool call. Moosend has not shipped that surface, and neither has its parent company.

i

No official Moosend MCP server exists

Verified August 19, 2026: the Moosend GitHub organisation holds 18 public repositories and none is MCP-related, docs.moosend.com never mentions MCP, and public directories list no first-party implementation. Constant Contact, owner since June 2025, has none either, no parent-company umbrella to inherit. Agent access runs through iPaaS servers that wrap the Moosend connector.

Available MCP servers

All three are third-party, none endorsed by Moosend, and none exposes the full v3 surface, you get whatever the intermediary modelled. Ranked by practicality.

Why buyers should care

MCP availability is a proxy for how alive a vendor’s developer organisation is, and Moosend’s absence fits the picture: SDKs untouched since 2017, release notes silent since February 2023, webhooks that exist only as an automation step. If agents writing to your ESP are on the 2026 roadmap, budget for your own MCP wrapper around the v3 API, or for paying an iPaaS to be that layer. Brevo and MailerLite sit in the same price band with fresher tooling.

Moosend API essentials

Moosend v3 is a resource-and-action API rather than a strict REST-verb API: writes are POST to a named action path such as /subscribe.json, reads are GET on a matching path. Two conventions catch out newcomers.

Base URLhttps://api.moosend.com/v3
Versionv3-the only documented version
Response formatSelected by path extension: .json or .xml. No Accept-header negotiation.
Authenticationapikey query-string parameter on every request
EnvelopeEvery response wraps payload in { Code, Error, Context }
PaginationPath segments: /campaigns/{Page}/{PageSize}.json. No cursor, no Link header.
Rate limitingPer-endpoint, per-key. HTTP 429 with {"Code": 429, "Error": "RATE-LIMITING"}
WebhooksAutomation-workflow action only, no subscription endpoints
Inbound parseNot offered
Request timeoutNot published, set your own client timeout

The format extension is load-bearing: /campaigns/create without .json is not the same route, and putting the query string before the extension produces a path Moosend does not recognise. Order is always path → .json → ?apikey=-centralise URL construction in one helper. Pagination has the same problem: {Page} and {PageSize} are positional segments, so omitting page size changes the route rather than applying a default, and no default is documented. Pass both, and stop paging when a collection returns shorter than the size you asked for.

Authentication methods

API key in the query string

There is exactly one documented method. Generate a key at More › Settings › API key and append it as ?apikey=YOUR_API_KEY. No Bearer token, no header key, no HMAC signing and no OAuth flow appears anywhere in the v3 reference, a connector that assumes header auth needs a special case for Moosend.

Keys inherit the creating role

A Moosend key is not a global credential: it carries the permissions of the role that generated it. Owner, Admin, Viewer, Manager, Designer, Admin observer or GDPR viewer, so a key made by a limited role only reaches what that role reaches. That is the closest thing to scoped keys on offer. For a read-only reporting key, create a dedicated user with a restricted role and generate the key as that user.

Query-string keys leak into places you do not control

Because the key travels as a URL parameter rather than a header, it lands in access logs, browser history, proxy logs, referrer headers and any error tracker capturing full request URLs. Treat a Moosend key as compromised the moment it reaches a log aggregator: never call the API from client-side JavaScript, scrub the apikey parameter in logging middleware, and rotate on a schedule rather than only after an incident.

Sub-accounts and the SMTP credential split

Sub-accounts carry their own credentials, so generate the key while signed in as the sub-account, a parent key does not reach sub-account data. The relay is a separate system: smtp.mailendo.com authenticates with your Moosend account login, and a sub-account uses a domain-prefixed username of the form myaccount\username. Moosend issues no SMTP-only credential, see SMTP settings.

Rate limits

Moosend publishes no global requests-per-minute figure. Limits are per endpoint, enforced per API key, and the spread is wide enough that your architecture depends on which endpoints you touch.

EndpointLimitPractical effect
POST subscribe10 calls / 10sAbout 1 subscriber/second sustained
POST subscribe_many2 calls / 10sPace bulk imports, never parallelise
POST transactional/send6 calls / 1sTightest per-second limit published
GET campaign stats2 calls / 60sDashboards must cache aggressively
Unsubscribe endpoints20 calls / 10sFine for preference-centre traffic
DELETE subscriber40 calls / 10sMost permissive documented endpoint
Batch delete subscribers8 calls / 10sPrefer to single deletes for GDPR sweeps

The workaround differs per pinch point. For migration, drive everything through subscribe_many at one call per five seconds and accept that a large import runs for hours, parallel single subscribe calls just produce a stream of 429s. For reporting, the 2 calls / 60s statistics ceiling makes per-campaign polling impractical: build on /view_summary.json, cache recipient-level activity for an hour or more, and refresh on a queue rather than on page load. For transactional volume, 6 calls / 1s is about 21,600 messages an hour at perfect saturation, fine for receipts, thin for a real transactional workload, where Postmark fits better. No Retry-After header is documented, so use exponential backoff with jitter.

Official SDKs

Moosend publishes API wrappers for nine languages. All are Swagger-generated and none is maintained: eight were last committed on October 2-3, 2017, the PHP wrapper alone reaching February 2020. Read them for request shapes; do not add them to a manifest.

LanguagePackageInstallRepo
JavaScriptmoosend-apinpm install moosend-api --savejs
PHPmoosend/api-wrappers-phpcomposer require moosend/api-wrappers-phpphp
Pythonmoosend_api_wrapperpip install git+https://github.com/moosend/api-wrappers-python.gitpython
C#, Java, Ruby, Go, Swift, ScalaSource only, no package publishedgit clone the repo6 repos in the Moosend org

Only two ship through a package manager: moosend-api on npm and moosend/api-wrappers-php on Packagist. The Python wrapper was never published to PyPI, installation is git-only and its README still advertises Python 2.7.

Do not add an official Moosend SDK as a production dependency in 2026

The JavaScript wrapper is callback-style with no Promise support, so no async/await. The Python wrapper predates f-strings. None of the nine has been patched for a transitive CVE in six to nine years. Because the API is trivially simple, one query parameter for auth, one path extension for format-requests, fetch or Guzzle is less code and materially safer.

Notable community SDKs

There is no meaningful third-party SDK ecosystem here. npm, PyPI and Packagist surface no maintained community client with real adoption, unsurprising for an API this thin, where a wrapper would be a hundred lines. The community routed around it with iPaaS connectors instead: the official Zapier app, the Make app in Moosend’s own directory, plus Pipedream, viaSocket, ApiX-Drive and Pabbly Connect. Any of those is a more realistic abstraction layer than a hand-rolled SDK, and Zapier doubles as your MCP path. The only first-party code with recent commits is the website tracking library (June 2024), a browser snippet, not an API client.

Endpoints reference

Fifteen of the most-used routes are below. Every path takes a {Format} extension of json or xml plus the apikey parameter. Request bodies and field types live in the official API documentation.

ResourceMethodDescription
Subscribers
/subscribers/{ListID}/subscribe.{Format}
POSTAdd one subscriber with custom fields.
Subscribers
/subscribers/{ListID}/subscribe_many.{Format}
POSTBulk-add subscribers in one call.
Subscribers
/subscribers/{ListID}/view.{Format}
GETLook up a subscriber by email address.
Subscribers
/subscribers/{ListID}/update/{SubscriberID}.{Format}
POSTUpdate a subscriber’s email or custom fields.
Subscribers
/subscribers/{ListID}/unsubscribe.{Format}
POSTUnsubscribe from a single list.
Subscribers
/subscribers/unsubscribe.{Format}
POSTUnsubscribe account-wide rather than per list.
Subscribers
/subscribers/{ListID}/remove.{Format}
POSTPermanently remove, distinct from unsubscribing.
Mailing lists
/lists/{Page}/{PageSize}.{Format}
GETPage active lists; /lists.json returns all.
Mailing lists
/lists/create.{Format}
POSTCreate a new empty mailing list.
Mailing lists
/lists/{ListID}/subscribers/{Status}.{Format}
GETMembers by status: Subscribed, Bounced, Removed.
Custom fields
/lists/{ListID}/customfields/create.{Format}
POSTDefine a custom field; update and delete share the prefix.
Segments
/lists/{ListID}/segments/create.{Format}
POSTCreate a segment, then add /criteria/add.json rules.
Campaigns
/campaigns/create.{Format}
POSTCreate a draft; edit via /{CampaignID}/update.json.
Campaigns
/campaigns/{CampaignID}/send.{Format}
POSTSend a draft now; /schedule and /send_test exist too.
Transactional
/campaigns/transactional/send.{Format}
POSTSend a transactional message.

Code examples

Verify a key and list senders (curl)

Moosend has no ping endpoint. /senders/find_all.json is the cheapest read that proves a key works, and it doubles as the fastest way to confirm from code that a sending domain cleared SPF, DKIM and DMARC.

curl -s "https://api.moosend.com/v3/senders/find_all.json?apikey=YOUR_API_KEY"

# Success looks like:
# { "Code": 0, "Error": null, "Context": { "Senders": [ ... ] } }
#
# A bad key still returns HTTP 200. Check Error, not the status code.

Add a subscriber (Python)

import requests

API_KEY = "YOUR_API_KEY"
LIST_ID = "YOUR_MAILING_LIST_ID"
BASE = "https://api.moosend.com/v3"

# Note the .json extension and the apikey QUERY parameter - Moosend has
# no header-based auth and no Accept-header negotiation.
url = f"{BASE}/subscribers/{LIST_ID}/subscribe.json"

resp = requests.post(
    url,
    params={"apikey": API_KEY},
    json={
        "Name": "Ada Lovelace",
        "Email": "ada@example.com",
        "CustomFields": ["Country=Greece", "Plan=Pro"],
    },
    timeout=30,
)

# {"Code": 429, "Error": "RATE-LIMITING"} - subscribe is capped at 10 calls / 10s
if resp.status_code == 429:
    raise SystemExit("Rate limited by Moosend, back off and retry")

data = resp.json()

# Moosend returns HTTP 200 even for logical failures: always check Error.
if data.get("Error"):
    raise SystemExit(f"Moosend error: {data['Error']}")

print(data["Context"])

Custom fields are an array of Name=Value strings rather than an object, and each must already exist on the list, posting an unknown field name returns HTTP 200 with a populated Error.

Add a subscriber (Node)

// The official 'moosend-api' package is untouched since 2017 - use fetch.
const { MOOSEND_API_KEY: KEY, MOOSEND_LIST_ID: LIST } = process.env;

async function subscribe(email, name) {
  const url = `https://api.moosend.com/v3/subscribers/${LIST}`
            + `/subscribe.json?apikey=${KEY}`;

  const res = await fetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ Name: name, Email: email,
      CustomFields: ["Country=Greece", "Plan=Pro"] }),
  });

  if (res.status === 429) throw new Error("RATE-LIMITING: 10 calls / 10s");

  // Every response is { Code, Error, Context } with HTTP 200 even on
  // failure - never trust the status code alone.
  const data = await res.json();
  if (data.Error) throw new Error(`Moosend error: ${data.Error}`);
  return data.Context;
}

Common gotchas

HTTP 200 does not mean success

Moosend v3 returns 200 for failures other APIs signal with a 4xx: an unknown list ID, an invalid custom field name, a malformed address. Code branching on response.ok or resp.status_code alone treats these as successes and silently drops subscribers, invisible until someone notices a list is not growing. Parse the body and assert Error is null before trusting Context. Only rate limiting surfaces as a real status, at 429.

Statistics and bulk import are the limits that bite

Campaign statistics allow 2 calls per 60 seconds, so a dashboard polling per-campaign metrics beyond a handful of campaigns needs an aggressive cache. Bulk import allows 2 calls per 10 seconds, so a large migration must be paced rather than fanned out across workers, going one at a time to dodge the batch limit is slower in aggregate.

Webhooks cannot be registered, catalogued or verified

Moosend’s webhook capability exists only as a “Then post a webhook” step inside an automation, POSTing JSON to a URL you type into the builder. There is no endpoint to register, list or delete subscriptions, no event catalogue for bounce or complaint, and no documented HMAC signature, retry policy or payload size limit, so you cannot verify an inbound POST came from Moosend. Mitigate with a long unguessable receiver path plus an IP allowlist, and treat payloads as untrusted.

SMTP and API credentials are separate systems

An API key does not authenticate the relay, and account credentials do not authenticate the API. The relay at smtp.mailendo.com uses your Moosend account login over STARTTLS on port 587. Ports 465 and 25000 were retired on October 1, 2025 and port 25 is unencrypted, so 587 is the only encrypted path. Rotating the account password rotates the relay password too, detail on the SMTP settings tab.

Deprecations and changelog

Moosend’s official release notes have been silent since early 2023, so the two most consequential recent changes, an ownership transfer and an SMTP port retirement, were announced elsewhere. The record below stitches those sources together.

  • October 1, 2025-SMTP ports 465 and 25000 retired; port 587 with STARTTLS becomes the only supported submission path. Automations and API campaigns were unaffected.
  • June 6, 2025-Constant Contact announces its acquisition of Moosend from Sitecore. Moosend continues as a standalone brand and keeps powering Sitecore Send. Any source still calling Moosend “Sitecore-owned” is out of date.
  • February 1, 2023-Sitecore Content Hub DAM integration ships. This is the final entry on the official “What’s new in Moosend” page.
  • December 1, 2022-Moosend migrates its API documentation to a tri-pane layout with outline, content and code samples side by side. The last developer-facing change on record.
  • May 3, 2021-Sitecore completes its acquisition of Moosend, later white-labelling the platform as Sitecore Send.

No API version has been deprecated: v3 is the only documented version and no v4 is announced. The real risk is stagnation, not a version cut. Check the official release notes before assuming anything here has changed, and read the absence of entries as data.

Frequently asked questions

How do I get a Moosend API key?

Go to More › Settings › API key and append the value to every request as ?apikey=YOUR_API_KEY. The key inherits the permissions of the role that generated it. Owner, Admin, Viewer, Manager, Designer, Admin observer or GDPR viewer, so for a read-only key, create a restricted-role user and generate it as that user. Sub-accounts need their own key.

What is the Moosend API rate limit?

There is no global limit; limits are per endpoint, per key. subscribe allows 10 calls / 10s, subscribe_many 2 / 10s, unsubscribe 20 / 10s, delete 40 / 10s, batch delete 8 / 10s, transactional send 6 / 1s, and campaign statistics just 2 / 60s. Breaching one returns HTTP 429 with {"Code": 429, "Error": "RATE-LIMITING"} and no Retry-After header, so use backoff with jitter.

Does Moosend have a REST API and what version is it?

Yes. REST API v3 at https://api.moosend.com/v3, the only documented version, with no successor announced. Two conventions differ from modern ESP APIs: response format comes from a .json or .xml path extension rather than an Accept header, and pagination uses positional path segments such as /campaigns/{Page}/{PageSize}.json. Coverage spans subscribers, lists, custom fields, segments, campaigns, reporting and transactional sends.

How do I add a subscriber via the Moosend API?

POST to /subscribers/{MailingListID}/subscribe.json?apikey=YOUR_API_KEY with Name, Email and optionally CustomFields-an array of Name=Value strings, each field already defined on the list. Capped at 10 calls / 10s; use subscribe_many.json at 2 calls / 10s for imports. Always check the Error field: a bad list ID returns HTTP 200 with the error inside.

Does Moosend support webhooks?

Only as an automation action, not a subscribable event API. You add a “Then post a webhook” step inside a workflow and supply a URL; Moosend POSTs JSON when the step is reached. There is no endpoint to register or delete subscriptions, no catalogue of delivery events such as bounced or complained, and no documented HMAC signature, retry policy or payload size limit. For subscriber events without automations, the official Zapier app offers New Subscriber, Updated Profile and New Unsubscriber triggers.

Is there an official Moosend MCP server?

No. As of August 2026 none exists: the Moosend GitHub organisation holds 18 public repositories with none MCP-related, docs.moosend.com does not mention MCP, and public directories list nothing. No dedicated community server was found either, and Constant Contact, owner since June 2025, has none. Agent access runs through iPaaS servers; Zapier MCP is the most practical, since Moosend is not a premium Zapier app. Re-verify before committing to an architecture.

Changelog (recent)

  • 2025-10-01 Moosend retires SMTP ports 465 and 25000. Port 587 with STARTTLS becomes the only supported submission path; automations, API campaigns and landing pages unaffected.
  • 2025-06-06 Constant Contact announces its acquisition of Moosend from Sitecore. Moosend continues as a standalone brand and keeps powering Sitecore Send. Terms undisclosed.
  • 2023-02-01 Sitecore Content Hub DAM integration ships, the final entry on the official What’s new in Moosend page. No releases published there since.
AAlaa Touil RRabeb How we test →

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