SparkPost logo

SparkPost API + MCP (2026): stable v1 REST, no first-party MCP

SparkPost’s REST API has been on v1 since 2014 and remains the single source of truth for the platform — every send, template, webhook and metric flows through the same JSON surface exposed at api.sparkpost.com (US) and api.eu.sparkpost.com (EU). Official SDKs cover 6 languages but most were last tagged in 2018–2021, so teams shipping new integrations increasingly call the REST API directly. For AI agents the story is thinner: as of August 2026 there is no first-party MCP server, only three third-party wrappers (Zapier, Vinkius, MCP Bundles) built on top of the public API.

At a glance

v1
REST API version
Stable since 2014, JSON over HTTPS, US + EU endpoints

6
Official SDKs
Python, Node.js, PHP, Go, Java + Nodemailer transport

3rd-party
MCP status (2026)
No official server — Zapier + Vinkius + MCP Bundles wrappers

MCP integration in 2026

SparkPost (owned by Bird, formerly MessageBird since November 2021) has not shipped a first-party Model Context Protocol server. The public REST API is stable and well-scoped, so third-party MCP wrappers appeared quickly — but if your compliance team requires a vendor-audited MCP surface for LLM agents, SparkPost is not there yet in 2026. Compare with Postmark and Resend, whose newer developer-first APIs have attracted more community MCP work, and SendGrid, which is in the same “wrapper-only” position.

i

No official SparkPost MCP server as of August 2026

SparkPost / Bird publishes no first-party MCP endpoint. All three usable servers are third-party wrappers over the public v1 REST API — Zapier MCP (Send Email action), Vinkius (~10 tools) and MCP Bundles (7 read-only list tools). For audited first-party coverage, use the REST API directly from your agent or wait for a Bird announcement.

Available MCP servers

Three hosted MCP surfaces are available today. All three read a SparkPost API key you provision yourself (US or EU region), so credential rotation stays inside your SparkPost account.

Why buyers should care. The absence of a first-party MCP server is not a blocker — SparkPost’s REST API is small enough (roughly 15 top-level resources) that a bespoke MCP shim is a one-afternoon project. What it does mean: no vendor SLA on the MCP layer, no guarantee of parity when SparkPost ships new endpoints, and every third-party server hosts your API key on its own infra. If that is a compliance issue, provision the key with the minimum scope, rotate on a schedule, and prefer the read-only MCP Bundles surface for exploratory agents.

SparkPost API essentials

Base URL (US)https://api.sparkpost.com/api/v1
Base URL (EU)https://api.eu.sparkpost.com/api/v1
API versionv1 — stable since 2014, no v2 announced
Response formatJSON (UTF-8), Content-Type: application/json
Pagination (Events)Cursor-based — cursor starts at initial, next cursor returned in links.next; default per_page 1000, max 10,000
Pagination (lists)Simple limit / offset or per_page on most other list endpoints
Bulk operationsOne Transmissions call can address up to 1,000 recipients
RegionsUS and EU are separate accounts — a US key does not work against the EU endpoint and vice versa
AuthAPI key in Authorization header (no Bearer prefix)
Content typesapplication/json for requests; UTF-8 required for non-ASCII substitution data

The API is organised around 15 top-level resources: Transmissions (create/list/cancel sends), Templates, Sending Domains, Tracking Domains, Inbound Domains, Relay Webhooks, event Webhooks, Events Search, Metrics/Deliverability, Suppression List, Recipient Lists, Recipient Validation, Subaccounts and IP Pools / Sending IPs. Most write endpoints accept the same JSON shape you would post via SMTP, so the API and SMTP relay share a mental model — useful when migrating from providers like Amazon SES or Brevo where the two channels are more decoupled.

Authentication methods

API key in Authorization header

The primary method. Provision an API key in the SparkPost dashboard under Configuration › API Keys, scope it to the minimum permissions needed (Transmissions: Read/Write, plus any specific resources), then send it as the raw Authorization header value — no Bearer or Basic prefix. Example:

curl -H "Authorization: 1234567890abcdef1234567890abcdef12345678" 
     https://api.sparkpost.com/api/v1/account

This differs from SendGrid and Postmark, which use Authorization: Bearer <key> and X-Postmark-Server-Token respectively. Copying a SendGrid header into a SparkPost request is one of the most common early-stage 401s.

HTTP Basic auth

For toolchains that only speak Basic auth, SparkPost accepts the API key as the username with an empty password. The equivalent curl:

curl -u "1234567890abcdef1234567890abcdef12345678:" 
     https://api.sparkpost.com/api/v1/account

SMTP AUTH LOGIN (SMTP endpoint only)

For the SMTP relay, authentication is unusual: the username is the literal string SMTP_Injection (case-sensitive), and the password is a SparkPost API key that carries the Send via SMTP permission. For subaccounts, append :X-MSYS-SUBACCOUNT=<subaccount_id> to the username. See the SparkPost SMTP tab for the full config.

Scope caveat. API-key permissions in SparkPost are granular per resource, not RBAC. A key scoped only to Transmissions: Read/Write cannot list templates or read metrics — you will get 403 with a helpful error body, not a silent failure. Provision one broad key for backend services and separate narrow keys for third-party MCP surfaces and CI runners; SparkPost lets you have as many keys as you like and rotate them individually.

Rate limits

LimitValueNotes
Recipients per Transmissions call1,000Sum of To + Cc + Bcc + archive lists — hard cap, chunk larger sends client-side
Message payload size20 MBHTML + text + attachments + inline images combined per message
Events Search page size10,000 maxDefault 1,000; pagination consumes rate-limit budget
Sandbox domain volume5 messages totalOnly on sparkpostbox.com, only to the account owner’s verified address
Free-plan monthly cap100,000/monthRequires a valid credit card once exceeded; enforced with HTTP 420, not 429
API RPM / RPSNot publicly documentedSignalled per endpoint with HTTP 429; varies by plan tier and endpoint class (transactional vs query)

SparkPost’s rate-limit philosophy is closer to Amazon SES than to SendGrid: there is no single account-wide RPM published in the docs, and the platform enforces a mix of monthly volume caps (HTTP 420 Enhance Your Calm) and per-endpoint throttles (HTTP 429) that you discover empirically. The pragmatic workaround: keep a jittered exponential-backoff wrapper around Transmissions and Events calls, respect the Retry-After header when present, and shift heavy Events queries to a nightly cron rather than the request path. High-volume customers (3M+ per month) can negotiate guaranteed burst rates as part of the Enterprise contract.

Official SDKs

SparkPost publishes SDKs for 6 stacks. All target the v1 REST API and cover the common surface (Transmissions, Templates, Suppressions, Webhooks) — but as of 2026 most release cadences are slow, and newer resources like Events Search and Signals Analytics are often easier to consume by calling the REST API directly.

LanguagePackageInstallRepo
Pythonsparkpostpip install sparkpostSparkPost/python-sparkpost — last tag 1.3.10 (Nov 2021)
Node.jssparkpostnpm install sparkpostSparkPost/node-sparkpost — last tag 2.1.3 (Oct 2018)
PHPsparkpost/sparkpostcomposer require sparkpost/sparkpostSparkPost/php-sparkpost — renamed from sparkpost/php-sparkpost at 2.0, maintenance PRs still merging
Gogithub.com/SparkPost/gosparkpostgo get github.com/SparkPost/gosparkpostSparkPost/gosparkpost — community-maintained, tracks REST surface
Javacom.sparkpost:sparkpost-libMaven / Gradle dependencySparkPost/java-sparkpost — low release cadence
Nodemailer transportnodemailer-sparkpost-transportnpm install nodemailer-sparkpost-transportSparkPost/nodemailer-sparkpost-transport — official Nodemailer transport

SDK staleness — plan accordingly. The official Node SDK’s last tagged release is October 2018 and the Python SDK’s is November 2021. Both still work against v1 for the common send/template/suppression paths — but Events Search cursors, Inline Seeds and Signals Analytics are safer to call directly with requests / axios. If you need long-term support, budget a small internal wrapper rather than pinning to an SDK version.

Notable community SDKs

Beyond the six official clients, the ecosystem is small but functional: nodemailer-sparkpost-transport for any Node app that already speaks Nodemailer, a maintained Django backend at django-sparkpost, a Symfony Mailer bridge in the mainline Symfony repo, Laravel’s built-in SparkPost mail driver (deprecated in Laravel 9 but still functional via community shims), and the official Postman collection covering the full v1 surface. For Rust / Elixir / Kotlin there is no maintained wrapper — call the REST API directly.

Endpoints reference

The full API surface is 15 top-level resources. Full reference lives at the SparkPost Developer Hub; the table below is the short list you will use in practice.

ResourceMethodsDescription
Transmissions
/api/v1/transmissions
POST, GET, DELETECreate, list and cancel outbound email transmissions (single or bulk, immediate or scheduled).
Templates
/api/v1/templates
GET, POST, PUT, DELETECRUD for stored templates with substitution data and preview-with-substitution.
Sending Domains
/api/v1/sending-domains
GET, POST, PUT, DELETERegister, verify (DKIM / SPF / ownership) and manage sending domains.
Tracking Domains
/api/v1/tracking-domains
GET, POST, PUT, DELETEManage custom domains for click/open tracking pixels and link rewrites.
Inbound Domains
/api/v1/inbound-domains
GET, POST, DELETEConfigure domains for parsing inbound email through Relay Webhooks.
Relay Webhooks
/api/v1/relay-webhooks
GET, POST, PUT, DELETERegister HTTP endpoints that receive inbound (relay) email payloads.
Webhooks (events)
/api/v1/webhooks
GET, POST, PUT, DELETERegister push webhooks for delivery, bounce, open, click and other engagement events.
Events (search)
/api/v1/events/message
GETCursor-paginated search of message events with rich filters and up to 10,000 per page.
Message Events (legacy)
/api/v1/message-events
GETLegacy event query endpoint (superseded by Events Search).
Metrics / Deliverability
/api/v1/metrics/deliverability
GETAggregate deliverability metrics (delivered, bounces, opens, clicks) by many dimensions.
Suppression List
/api/v1/suppression-list
GET, PUT, DELETEManage transactional and non-transactional suppressions (bounces, unsubscribes, complaints).
Recipient Lists
/api/v1/recipient-lists
GET, POST, PUT, DELETEStore reusable recipient lists with per-recipient substitution data.
Recipient Validation
/api/v1/recipient-validation/single/{email}
GETReal-time single-address validation (paid add-on).
Subaccounts
/api/v1/subaccounts
GET, POST, PUTProvision and manage subaccounts (compartmentalised tenants) inside a parent account.
IP Pools & Sending IPs
/api/v1/ip-pools, /api/v1/sending-ips
GET, POST, PUT, DELETEGroup and assign dedicated sending IPs into pools for reputation isolation.

Code examples

Python — send a templated transactional email

from sparkpost import SparkPost

sp = SparkPost('YOUR_SPARKPOST_API_KEY')  # or set SPARKPOST_API_KEY env var
# For EU: SparkPost('YOUR_SPARKPOST_API_KEY', base_uri='https://api.eu.sparkpost.com')

response = sp.transmissions.send(
    recipients=[{'address': 'user@example.com'}],
    from_email='hello@yourverifieddomain.com',
    subject='Hello from SparkPost',
    html='<p>Hi <strong>{{name}}</strong>, this is a test.</p>',
    text='Hi {{name}}, this is a test.',
    substitution_data={'name': 'Friend'},
    track_opens=True,
    track_clicks=True,
)

print(response['id'], response['total_accepted_recipients'])

Node.js — same call with the official SDK

const SparkPost = require('sparkpost');
// For EU: new SparkPost('YOUR_SPARKPOST_API_KEY', { origin: 'https://api.eu.sparkpost.com' })
const client = new SparkPost('YOUR_SPARKPOST_API_KEY');

client.transmissions.send({
  content: {
    from: 'hello@yourverifieddomain.com',
    subject: 'Hello from SparkPost',
    html: '<p>Hi <strong>{{name}}</strong>, this is a test.</p>',
    text: 'Hi {{name}}, this is a test.',
  },
  substitution_data: { name: 'Friend' },
  recipients: [{ address: 'user@example.com' }],
  options: { open_tracking: true, click_tracking: true },
})
.then(data => console.log('Sent:', data.results.id))
.catch(err => console.error('SparkPost error:', err));

Raw curl — when you cannot pin an SDK

curl -X POST https://api.sparkpost.com/api/v1/transmissions 
  -H "Authorization: YOUR_SPARKPOST_API_KEY" 
  -H "Content-Type: application/json" 
  -d '{
    "options": { "open_tracking": true, "click_tracking": true },
    "content": {
      "from": "hello@yourverifieddomain.com",
      "subject": "Hello from SparkPost",
      "html": "<p>Hi <strong>{{name}}</strong>, this is a test.</p>",
      "text": "Hi {{name}}, this is a test."
    },
    "substitution_data": { "name": "Friend" },
    "recipients": [ { "address": "user@example.com" } ]
  }'

Common gotchas

US and EU accounts hit different endpoints — and fail silently

SparkPost EU accounts (created at eu.sparkpost.com) will return 401 or empty responses against the US endpoints. Use smtp.eu.sparkpostmail.com for SMTP and https://api.eu.sparkpost.com/api/v1 for REST. Every official SDK accepts a base_uri / origin option — set it once at client init rather than sprinkling it per call. Getting this wrong is the single most common cause of “my key does not work” support tickets in the SparkPost community forum.

The Authorization header takes the raw key — no Bearer prefix

Unlike SendGrid, MailerSend and most modern APIs, SparkPost expects Authorization: <key> with no scheme prefix. If you paste Authorization: Bearer <key> you get 401 Unauthorized. This trips up teams migrating from SendGrid or Resend who assume the header shape is universal.

Events Search cursor budget consumes rate limits

The Events Search endpoint is powerful (10,000 events per page, rich filters) but every cursor request counts against the account’s per-endpoint rate limit. A backfill loop that walks 30 days of history in a tight while cursor can burn the budget for the whole account and start rejecting production Transmissions calls. Add time.sleep(0.5) between pages, respect Retry-After, and run backfills off-peak.

1,000 recipient cap per Transmissions call is a hard limit

A single POST /transmissions can address at most 1,000 recipients across To, Cc, Bcc and archive lists combined. Larger sends must be chunked client-side — there is no server-side auto-split. Total payload (HTML + text + attachments + inline images) is capped at 20 MB regardless of recipient count. Compare with Amazon SES (50 recipients per SendEmail, 10 MB payload) and Postmark (500 per batch).

Monthly cap fires HTTP 420, not 429

When you cross the free-plan 100,000/month cap without a credit card on file, or a paid tier’s monthly volume ceiling, SparkPost returns HTTP 420 Enhance Your Calm — not the usual 429 Too Many Requests. A generic retry helper that only treats 429 as retryable will treat 420 as a permanent failure and drop the message. Extend your retry classifier to include 420 with a much longer backoff (hours, not seconds) or, better, wire a Signals Analytics alert on approaching the monthly ceiling.

Deprecations and changelog

  • February 1, 2024 — Gmail and Yahoo bulk-sender requirements (DMARC, one-click List-Unsubscribe, <0.3% spam complaint rate) become enforceable. SparkPost ships Signals Analytics guidance for reaching the complaint threshold and updates the official WordPress plugin to add List-Unsubscribe headers by default.
  • February 8, 2023 — MessageBird rebrands to Bird. The SparkPost email product keeps shipping under the SparkPost name and endpoints (sparkpost.com, sparkpostmail.com), gradually surfaced under bird.com.
  • November 24, 2021 — SparkPost acquired by MessageBird, joining what would become the Bird platform. API and SMTP endpoints preserved unchanged.
  • November 9, 2021python-sparkpost 1.3.10 released. Last tagged release of the official Python SDK; still compatible with the v1 REST API but new resources require calling the API directly.
  • April 29, 2021 — Sending Domains API adds the scph<selector> DKIM CNAME rotation used by all new domains from that date forward (selector prefix scph0421).

Full release notes: SparkPost Developer Hub release notes.

Frequently asked questions

What is the base URL of the SparkPost REST API and how do I authenticate?

Two base URLs depending on account region: https://api.sparkpost.com/api/v1 for US accounts and https://api.eu.sparkpost.com/api/v1 for EU accounts. Authenticate by putting the raw API key in the Authorization header — no Bearer prefix. A curl smoke test: curl -H "Authorization: <key>" https://api.sparkpost.com/api/v1/account. HTTP Basic auth also works with the key as the username and an empty password.

Which official SDKs does SparkPost publish and are they still maintained?

Six official clients: Python (sparkpost, last tag 1.3.10 in Nov 2021), Node.js (sparkpost, last tag 2.1.3 in Oct 2018), PHP (sparkpost/sparkpost, still receiving maintenance PRs), Go (gosparkpost, community-maintained), Java (com.sparkpost:sparkpost-lib, low cadence), plus the nodemailer-sparkpost-transport. All still work against v1 for common send/template/suppression paths — but newer resources like Events Search cursors and Signals Analytics are easier to call directly with requests or axios.

How does pagination work on the SparkPost Events API?

The Events Search endpoint (GET /api/v1/events/message) uses cursor pagination. First request: cursor=initial with a per_page between 1 and 10,000 (default 1,000). The response includes a links.next URL containing the next cursor. Loop until links.next is absent. Each page counts against the endpoint’s rate limit, so sleep between pages when backfilling. Other list endpoints use simple limit / offset or per_page.

What are the SparkPost API rate limits and how are they signalled?

SparkPost does not publish a single account-wide RPM/RPS. Per-endpoint throttles are signalled with HTTP 429 plus a Retry-After header, and monthly volume ceilings fire HTTP 420 Enhance Your Calm (not 429 — a common trap for generic retry helpers). Hard payload limits: 1,000 recipients per Transmissions call, 20 MB per message, 10,000 per Events page. Enterprise contracts (3M+/month) can negotiate guaranteed burst rates.

Does SparkPost offer an official MCP server for AI agents in 2026?

No. As of August 2026 SparkPost / Bird publishes no first-party MCP server. Three third-party wrappers exist on top of the public REST API: Zapier MCP for SparkPost (exposes the Send Email action and everything else the Zapier SparkPost app supports), Vinkius SparkPost MCP (~10 tools, commercial), and MCP Bundles (7 read-only list tools). None come with vendor-level SLAs on the MCP layer.

How do I send a templated transactional email with substitution data via the Transmissions API?

POST /api/v1/transmissions with a body containing content (from, subject, html, text or template_id), recipients (array of {address, substitution_data}) and optional top-level substitution_data for defaults. SparkPost merges per-recipient substitutions over defaults, so you can define {"name": "Friend"} at the top level and override per recipient. See the curl example above. Response includes results.id (the transmission id) and total_accepted_recipients.

Changelog (recent)

  • 2024-02-01 Gmail and Yahoo bulk-sender requirements (DMARC, one-click List-Unsubscribe, <0.3% spam complaint rate) become enforceable; SparkPost publishes Signals Analytics guidance and adds List-Unsubscribe headers by default in the official WordPress plugin.
  • 2023-02-08 MessageBird rebrands to Bird; SparkPost email product continues to ship under the SparkPost name and endpoints, gradually surfaced under bird.com.
  • 2021-11-24 SparkPost acquired by MessageBird, joining what would become the Bird platform; API and SMTP endpoints preserved under sparkpost.com and sparkpostmail.com.
AAlaa Touil RRabeb How we test →

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