SparkPost (now Bird Email) is a serious enterprise sender; its inbound is Relay Webhooks — it POSTs a batched JSON array of relay messages carrying the raw RFC822 email, with no normalized auth verdict. MailKite gives your agent a real inbox: one parsed email.received event with decoded text/HTML, a threadId, and an auth block, plus sending in the same API.
SparkPost is a genuine sending heavyweight — years of ISP relationships, mature analytics, suppression management, and IP-warming for high-volume outbound. Its Relay Webhooks inbound feature is real and documented, and under Bird it sits in a broader omnichannel platform (email, SMS, WhatsApp). If your agent's job is mostly to send at scale, that's a reasonable home.
SparkPost POSTs a JSON array of msys.relay_message objects that you de-batch yourself. MailKite delivers one email.received event per message — no loop, no batch handling before your agent can act.
The relay payload gives no normalized SPF/DKIM/DMARC result — you regex it out of the raw Authentication-Results header. MailKite hands your agent an auth{spf,dkim,dmarc,spam} verdict it can branch on directly, which matters when an LLM will follow what the mail says.
SparkPost puts the raw RFC822 in content.email_rfc822, base64-encoded only when a flag says so, and leaves MIME parsing to you. MailKite gives you decoded text and html fields and signed attachment URLs — the edge did the parse.
MailKite threads replies for you (from: event.to[0], inReplyTo: event.id), and a route with action:'agent' runs the whole receive→reply loop on a durable queue with a transcript. SparkPost is sending-first and has no agent runtime.
| MailKite | SparkPost (Bird) | |
|---|---|---|
| Inbound shape | One email.received event per message | Batched JSON array of relay_message |
| Raw message | Decoded text / html fields | RFC822 in email_rfc822, base64 when flagged |
| Auth to the agent | auth{spf,dkim,dmarc,spam} verdict | None normalized; parse Authentication-Results yourself |
| Reply + threading | from: event.to[0], inReplyTo: event.id | Build From / In-Reply-To yourself |
| Agent runtime | BYO loop, or route action:'agent' on a queue | None — sending-first ESP |
| Outbound sending | First-class, shared quota | Yes — its core strength at scale |
| Getting started | DNS-verify, then send; 3,000 msgs/mo free | Enterprise, sales-led onboarding |
| Per-domain fees | None — unlimited domains | Enterprise plan / volume tiered |
Competitor capabilities change — we re-audit these tables regularly. Spot something out of date? Tell us and we'll fix it.
SparkPost hands you a batch of raw messages and lets you derive the trust signal; MailKite hands your agent one parsed message with the auth verdict already computed.
POST /hooks/sparkpost Content-Type: application/json
[
{ "msys": { "relay_message": {
"friendly_from": "ada@example.com",
"rcpt_to": "agent@myapp.ai",
"content": {
"email_rfc822": "UmVjZWl2ZWQ6IGZyb20g…", // raw RFC822
"email_rfc822_is_base64": true // …decode ONLY when true
}
} } }
]
// de-batch the array, branch on the base64 flag, run a MIME parser,
// then regex SPF/DKIM out of the raw Authentication-Results header —
// there is NO normalized auth verdict in the payload. POST /your-webhook Content-Type: application/json
x-mailkite-signature: t=…,v1=… (HMAC-SHA256 — verify locally)
{
"id": "msg_2Hk9…",
"type": "email.received",
"from": { "address": "ada@example.com" },
"to": [{ "address": "support@myapp.ai" }],
"subject": "Re: invoice #1042",
"text": "Looks good — approved!",
"html": "<p>Looks good — approved!</p>",
"threadId": "<a1b2c3@mail.example.com>",
"auth": { "spf": "pass", "dkim": "pass", "dmarc": "pass", "spam": "ham" },
"attachments": [
{ "filename": "po.pdf", "contentType": "application/pdf",
"size": 18213, "url": "https://api.mailkite.dev/att/2Hk9…/0?sig=…" }
]
} SparkPost prices for enterprise outbound volume; MailKite prices one combined inbound + outbound quota with every domain free — no sales call to start receiving.
Where SparkPost has you point MX at rx1/rx2/rx3.sparkpostmail.com and register a relay webhook, you add MailKite's MX records and DNS-verify — no inbound-domain + relay-webhook API dance.
Drop the array loop, the email_rfc822_is_base64 branch, the MIME parser, and the Authentication-Results regex. Read event.text, event.from.address, and event.auth straight off one JSON object.
Check x-mailkite-signature with the SDK's verifyWebhook helper, then reply through the same send API — from: event.to[0], inReplyTo: event.id threads it for you.
Yes — through Relay Webhooks. You register an inbound domain, point its MX at rx1/rx2/rx3.sparkpostmail.com, and SparkPost POSTs a batched JSON array of msys.relay_message objects carrying the raw RFC822 message. It receives fine; the work is that you de-batch, conditionally base64-decode, and MIME-parse it yourself. MailKite delivers one already-parsed email.received event instead.
Not as a normalized verdict. The relay-message payload has no SPF/DKIM/DMARC result fields — the auth signals live only in the raw message headers (Authentication-Results, Received-SPF), which you parse yourself. For an agent that must decide whether to trust a sender before acting, that's meaningful work. MailKite's payload includes an auth block with spf, dkim, dmarc, and a spam verdict.
Effectively yes. MessageBird acquired SparkPost in 2021 and rebranded the product to Bird Email in 2023. The naming is split-brain today: marketing has moved to bird.com while the developer API reference still lives at developers.sparkpost.com and the inbound relay-webhook feature still uses the api.sparkpost.com surface — expect to cross both brands when evaluating it.
The SparkPost alternative for AI agents →
The long-form take on our blog — receipts, runnable code, and where we won't overclaim.
Point a domain, drop in a webhook URL, receive your first email. Unlimited domains, no credit card.