SendPulse ships an unversioned REST API at api.sendpulse.com, one OAuth 2.0 client_credentials token that unlocks every channel it sells, and — unusually for a mid-market ESP — an official Model Context Protocol server at mcp.sendpulse.com/mcp, live since November 26, 2025. One credential drives bulk email, SMTP transactional, SMS, web push, CRM, Courses and seven chatbot channels, and an AI client can drive most of it without glue code.
The counterweight is depth: six thin SDKs with low commit velocity, none covering the chatbot, CRM or Courses endpoints, and a reference split service by service. On ergonomics alone, Brevo and MailerLite document better. On breadth per credential and MCP readiness, SendPulse leads its price bracket.
Model Context Protocol lets an AI client call a vendor’s API as typed tools instead of you hand-rolling a wrapper. Most ESPs are still at the community-wrapper stage. SendPulse is not: it runs a first-party server, and it separately acts as an MCP client inside its chatbot builder — a different capability that the same search query surfaces.
A hosted endpoint at https://mcp.sendpulse.com/mcp, announced November 26, 2025. Authentication is browser login or OAuth 2.0 with the same Client ID and Client Secret as the REST API, both copyable from Account settings › API. Coverage spans the chatbot builder, CRM, Courses, email and SMTP — launch scope was chatbots and CRM only, so email and SMTP tooling arrived later and pop-ups remain the thinnest surface.
Two official surfaces plus third-party wrappers that predate them. The community entries were not functionally verified and none match the official coverage — narrow fallbacks, not alternatives. Further listings on mcpmarket and LobeHub exist but show placeholder slugs and no maintenance signal.
Hosted at mcp.sendpulse.com/mcp. Tools follow a service_resource_action pattern: email_addressbooks_get, chatbots_bots_list, push_tasks_send.
The reverse direction: under Bot settings › Integrations › MCP servers, paste an external MCP URL, authenticate with a Bearer token or custom headers, and your Telegram or WhatsApp bot calls your own backend mid-conversation.
The Zapier action set only: add, update, delete subscriber, unsubscribe, change variable. Useful for putting SendPulse behind one endpoint with other Zapier apps; far narrower than the official server.
Independent server scoped to the chatbot API, predating the official launch and unaffiliated with SendPulse. Superseded in practice.
MCP changes who can operate the tool. With the server connected, an operator asks Claude or ChatGPT to list address books, create a template, fire a web push task or pull CRM deals without touching the dashboard — removing the most common reason ESP automation stalls in teams with no developer on call. Three checks: coverage is per service, not per endpoint, so confirm your action has a tool; pop-ups are the newest surface; and MCP inherits account permissions, so an agent holding your credentials can send real campaigns to real people.
Verified clients as of August 2026: Claude (web, desktop, mobile, Cowork), Claude Code, ChatGPT, Cursor, VS Code with GitHub Copilot, Cherry Studio, Antigravity, Devin and Cline. Compare GetResponse and Moosend, where 2026 MCP access is still community-built.
The API is not versioned at the root. Most resources sit directly under the domain — /smtp/emails, /addressbooks, /campaigns — while a few newer ones carry an inline segment such as /v2/email-service/smtp/sender_domains. There is no global /v1 prefix and no version header. Machine-readable OpenAPI specs are published per service, the fastest route to an accurate client where the HTML docs are thin.
| Base URL | https://api.sendpulse.com |
| Versioning | None at root NOTE inline /v2/ on selected resources |
| Response format | JSON |
| Auth | OAuth 2.0 client_credentials → Authorization: Bearer |
| Token lifetime | 1 hour |
| Pagination | Offset style: ?limit= and ?offset= |
| Batch ceiling | 500 emails per POST /smtp/emails/info |
| HTML payloads | Base64-encoded in the html field |
| OpenAPI specs | /.well-known/openapi/{service}.yaml |
| LLM-ready docs | /llms.txt, /llms-full.txt |
16 documented REST surfaces sit behind that one base URL: bulk email, SMTP transactional, SMS, web push, chatbots plus WhatsApp, Telegram, Messenger, Instagram, Viber, LiveChat and TikTok individually, CRM, Automation 360, email verification and Courses. What changes between them is the path prefix and the spec file, not the authentication — you integrate once and gain channels without renegotiating credentials.
Three credential systems exist, and confusing them is the most common integration failure. Two are API credentials; the third is the SMTP relay login, unrelated to the API.
Collect client_id and client_secret from Account settings › API, then POST /oauth/access_token with grant_type=client_credentials. The response carries an access_token valid 1 hour, sent as Authorization: Bearer <token> on every later request on every channel. There is no refresh token — re-run the same exchange.
SendPulse also accepts a static API key in the same Authorization: Bearer header, skipping the exchange. Simpler for a script, worse for anything long-lived — a static key cannot expire itself out of a leak.
The relay at smtp-pulse.com on ports 465, 587 and 2525 authenticates with your SendPulse login email plus a dedicated SMTP password generated under SMTP settings › General — a separate credential pair from client_id/client_secret. Full walkthrough on the SendPulse SMTP settings tab.
The token expires at exactly 1 hour and the SDKs do not all refresh transparently. Queue consumers hit surprise 401s about an hour into a deploy. Cache the token with its issue time and re-fetch at the 55-minute mark rather than reacting to failures.
The SMTP password is not the API secret. Authenticating against smtp-pulse.com with the API client_secret fails with a generic error naming neither credential. If the relay login is rejected, confirm the password came from SMTP settings › General, not Account settings › API.
Limits land in two unrelated places: the HTTP API has request-rate ceilings by plan tier, and the sending path has its own throughput and deliverability throttles. Exceeding the API ceiling returns HTTP 429.
| Limit | Value | Notes |
|---|---|---|
| API requests, Free | 1,000/min · 500,000/day | Both apply together |
| API requests, Standard | 2,000/min · 1M/day | Plan-tier scaling |
| API requests, Enterprise | 3,000/min · 3M/day | Highest tier |
| Over-limit response | 429 | Back off; token lives 1 hour |
| SMTP speed, Free | 50/hour · 400/day | Hard daily cap on free |
| SMTP speed, paid | 2,500 to 25,000/hour | Plan tier, not quota |
| Bounce throttle | >7% → 50/hour | Last 15 minutes |
| Error ceiling | >20 errors / 24h | Account blocked outright |
| Batch status lookup | 500 emails | Per /smtp/emails/info |
| Bulk campaigns | 4/hour | Separate from SMTP |
| Message size | 25 MB hard max | Over 1 MB bills as two |
The workarounds are boring and effective. Honour 429 with exponential backoff from one second, and batch where an endpoint allows it — one POST /smtp/emails/info covering 500 addresses replaces 500 single lookups. Hourly speed is a plan attribute: more quota does not make you faster, you move up a tier. And since the bounce throttle runs on a rolling 15-minute window, list hygiene is a throughput control, not only a deliverability one — poll GET /smtp/bounces/day and pause the queue when the ratio climbs.
Six client libraries under the sendpulse GitHub org, all thin wrappers over the same OAuth 2.0 flow rather than generated clients. Only PHP has real adoption.
| Language | Package | Install | Repo |
|---|---|---|---|
| PHP | sendpulse/rest-api | composer require sendpulse/rest-api | GitHub |
| Node.js | sendpulse-api | npm install sendpulse-api | GitHub |
| Python | pysendpulse | Clone repo, import pysendpulse | GitHub |
| Java | sendpulse-rest-api-java | Clone repo, add source | GitHub |
| Ruby | sendpulse-rest-api-ruby | Clone repo, require client | GitHub |
| C# | sendpulse-rest-api-csharp | Clone repo, add project ref | GitHub |
Only PHP (~117 stars) and Node.js (~50 stars) ship through a package manager. Python advertises no PyPI package, Java no Maven coordinates and Ruby no gem — the documented path for those three is cloning and vendoring: no dependency pinning, no automated security updates, a manual diff on every upstream fix. Java, Ruby and C# sit near 14 stars each.
None of the six wrap the chatbot, CRM or Courses surfaces. Most teams past the prototype stage skip the SDK: a small token-caching HTTP client covers every channel and ages better than a wrapper that stops at the email endpoints.
No community library has adoption worth naming. The SMTP feature page also advertises Objective-C, though no repository is surfaced. For any uncovered language, generate a client from the OpenAPI YAML at /.well-known/openapi/{service}.yaml rather than adopting an unmaintained wrapper — the specs are the most current artefact SendPulse publishes.
15 of the most-used paths, verified against the published docs and the chatbot Swagger reference. Full per-service specs sit at the OpenAPI index; the readable entry point is sendpulse.com/integrations/api.
| Resource | Methods | Description |
|---|---|---|
| Authorization /oauth/access_token | POST | Exchange client_id and secret for a Bearer token valid 1 hour. Required by every other endpoint. |
| Transactional email /smtp/emails | POST, GET | POST sends a transactional email, HTML base64-encoded. GET lists sent mail. |
| Email detail /smtp/emails/{id} | GET | Delivery detail and status for one email. |
| Batch status /smtp/emails/info | POST | Delivery info for up to 500 emails per request. |
| Send total /smtp/emails/total | GET | Total emails sent through the SMTP service. |
| Bounces /smtp/bounces/day | GET | Bounces over 24 hours; /total counts them. Watch it — 7% throttles you to 50/hour. |
| Unsubscribes /smtp/unsubscribe | GET, POST, DELETE | Read, add to or remove from the SMTP suppression list. |
| Sender domains /v2/email-service/smtp/sender_domains | GET, POST | List authenticated domains or POST /{domain} to add one. The API route to SPF and DKIM. |
| Senders and IPs /smtp/senders | GET | Confirmed senders. /smtp/ips returns the account’s sending IPs. |
| Mailing lists /addressbooks | GET, POST | Create and list address books. ?limit=/?offset=; /{id} takes GET, PUT, DELETE. |
| Contacts /addressbooks/{id}/emails | GET, POST, DELETE | Add, list and remove contacts. /emails/{email} spans all lists. |
| Campaigns /campaigns | GET, POST | Create and list campaigns; /{id} takes GET, PATCH, DELETE. Capped at 4/hour. |
| Templates /template | GET, POST | Create and read templates. /templates lists, /template/edit/{id} updates. |
| Chatbots /chatbots/bots | GET | List bots across every channel. Siblings: /dialogs, /operators, /operator-groups. |
| WhatsApp templates /whatsapp/templates | GET, POST, DELETE | Retrieve, create (for Meta review) and delete WhatsApp templates. Added July 2026. |
Every call starts with the token exchange. These use plain HTTP rather than an SDK, because that is what the chatbot, CRM and Courses surfaces require anyway.
curl -X POST https://api.sendpulse.com/oauth/access_token \
-H "Content-Type: application/json" \
-d '{"grant_type":"client_credentials",
"client_id":"YOUR_API_ID",
"client_secret":"YOUR_API_SECRET"}'
# {"access_token":"...","token_type":"Bearer","expires_in":3600}
# Cache it. Re-fetch at ~55 minutes, not on the first 401.import base64, requests
BASE = "https://api.sendpulse.com"
token = requests.post(f"{BASE}/oauth/access_token", json={
"grant_type": "client_credentials",
"client_id": "YOUR_API_ID",
"client_secret": "YOUR_API_SECRET",
}).json()["access_token"] # valid for 1 hour
body = "<h1>HTML body</h1>"
r = requests.post(f"{BASE}/smtp/emails",
headers={"Authorization": f"Bearer {token}"},
json={"email": {
"subject": "Hello from the SendPulse API",
"html": base64.b64encode(body.encode()).decode(), # base64 REQUIRED
"text": "Plain text body",
"from": {"name": "You", "email": "you@yourdomain.com"}, # confirmed
"to": [{"name": "Recipient", "email": "recipient@example.com"}],
}})
print(r.status_code, r.json())The html field is base64, not raw markup — passing HTML directly is the most frequent first-request failure. from.email must already be a confirmed sender on an authenticated domain, or the send is rejected regardless of quota.
// token obtained from /oauth/access_token as above
await fetch("https://api.sendpulse.com/smtp/emails", {
method: "POST",
headers: {
Authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
email: {
subject: "Hello from the SendPulse API",
html: Buffer.from("<h1>HTML body</h1>").toString("base64"),
text: "Plain text body",
from: { name: "You", email: "you@yourdomain.com" },
to: [{ name: "Recipient", email: "recipient@example.com" }],
},
}),
});{
"mcpServers": {
"sendpulse": { "url": "https://mcp.sendpulse.com/mcp" }
}
}
# Auth on first connect: browser login, or OAuth 2.0 with the
# Client ID / Secret from Account settings > API.A deliverability throttle sits on top of plan speed: a bounce rate above 7% cuts the account limit to the floor of 50 emails/hour, judged on the last 15 minutes. One bad batch can drop an account paying for 20,000/hour to 50/hour almost immediately, and more than 20 errors in 24 hours blocks the account. Validate lists before large sends and poll GET /smtp/bounces/day.
You cannot sign up and start relaying. SendPulse requires a completed profile (primary email, use case, how the list was collected, confirmation of an unsubscribe link), a confirmed address, then manual moderation of up to 24 hours. Service settings appear only after approval, so same-day cutovers stall here. Budget a day.
Billing is size-tiered, not per message. On paid plans, up to 1 MB counts as one email, 1–25 MB counts as two, and above 25 MB is not sent. On free, anything over 1 MB is not sent at all. Two inline images or a PDF invoice quietly doubles quota burn.
The SMTP relay (12,000 emails/month free, PAYG from $15 per 10,000) and Email Marketing (500 subscribers, 15,000 emails/month free, Standard from $9.60/month) have distinct pricing pages and limits. Upgrading the marketing plan does not raise SMTP hourly speed, and SMTP credits do not fund campaigns. The campaign API has its own cap of 4/hour.
One client_credentials token authorises bulk email, the SMTP API, SMS, web push, CRM, Courses and all seven chatbot channels — no separate chatbot key, no separate auth server. Two traps: the token expires at exactly 1 hour and the thin SDKs do not all refresh it, so long-running workers get surprise 401s; and the relay login is unrelated to client_id/client_secret, which is why authenticating to smtp-pulse.com with an API secret always fails.
SendPulse ships small, frequent updates, published on its official updates page. No API deprecations were announced in the window below.
POST /contacts/deleteVariable.GET /whatsapp/templates, POST to create and submit for Meta review, DELETE to remove.Copy client_id and client_secret from Account settings › API, then POST https://api.sendpulse.com/oauth/access_token with grant_type=client_credentials. It returns an access_token valid 1 hour, sent afterwards as Authorization: Bearer <token>. No refresh token — repeat the exchange. A static API key as Bearer also works.
Free: 1,000 req/minute and 500,000/day. Standard: 2,000/minute, 1,000,000/day. Enterprise: 3,000/minute, 3,000,000/day. Breaching either returns 429. Separate from sending throughput: SMTP hourly speed is a plan attribute, and a bounce rate above 7% collapses it to 50/hour regardless of API tier.
POST /smtp/emails with a Bearer token and an email object holding subject, html, text, from and to. The html value must be base64-encoded, and from.email must be a confirmed sender on an authenticated domain. Check delivery with GET /smtp/emails/{id}, or POST /smtp/emails/info for up to 500 at once.
Yes. A first-party server at https://mcp.sendpulse.com/mcp, announced November 26, 2025, covering the chatbot builder, CRM, Courses, email and SMTP. Authenticate by browser login or with the OAuth Client ID and Secret from Account settings › API. Supported clients include Claude, Claude Code, ChatGPT, Cursor, VS Code with GitHub Copilot, Cherry Studio, Antigravity, Devin and Cline.
No. The same token authorises bulk email, the SMTP API, SMS, web push, CRM, Courses and every chatbot channel. What differs is the path prefix (/telegram, /whatsapp, /instagram, /facebook, /viber, /tiktok, /chatbots) and the OpenAPI spec, not the authentication. The one separate credential is the SMTP relay login.
Six: PHP (composer require sendpulse/rest-api), Node.js (npm install sendpulse-api), Python, Java, Ruby, C#. Only PHP and Node.js ship through a package manager; the rest are clone-and-vendor. None wrap the chatbot, CRM or Courses surfaces, so those need a plain HTTP client or a generated client.
This review follows our email infrastructure testing methodology. We disclose affiliate relationships in our editorial independence policy.