Loops logo vs MailKite logo
Alternative to Loops

Keep Loops for product email — add an inbox your agent can actually read.

Loops is a genuinely nice lifecycle- and transactional-email tool for SaaS: a visual editor, event-triggered loops, and free transactional sends. But it's send-only, so an autonomous agent has nowhere to receive the verification code or the reply it's waiting on. MailKite gives that agent a real address that arrives as one parsed JSON webhook, and sends from the same API.

A fair take on Loops

Loops is one of the nicest developer experiences in product email right now — the visual editor is pleasant, the lifecycle-loops model maps cleanly to how SaaS onboarding works, and transactional sends are free on paid plans with clean Clerk/Stripe/Supabase integrations. If your job is sending lovely onboarding and product mail, Loops is a strong pick.

How it works

Loops vs MailKite, in one diagram

Loops (send-only) agentneeds a code Loops sendtransactional recipientgets the mail reply / codesent back no inboxnowhere to land MailKite (receives too) email inthe code MX edgeparse + auth JSON webhooksigned your agentyour model mk.send()reply out Blue = operated by MailKite. Loops does the top row well; it has no box for the reply. MailKite's lane closes the loop.
Why teams switch

What MailKite does differently

A real inbox, not just sending

Loops sends the welcome, the drip, and the receipt well — but an agent's hard problem is receiving. MailKite gives an address that receives, so the code emailed to agent@myapp.ai lands somewhere the agent can read.

One API for receive and send

Parse an incoming email and reply to it with the same account, SDK, and shared quota. With Loops you'd bolt on a second, receiving provider and reconcile threading between two systems.

Parsed JSON with auth built in

Inbound arrives as one JSON object — decoded text and HTML, a resolved threadId, signed attachment URLs, and an auth block (SPF/DKIM/DMARC/spam) so a fooled agent isn't a prompt-injection target.

Unlimited domains, free

Run every product and every agent address from one account at no per-domain cost, on every plan — instead of pricing by subscribed contacts.

Side by side

MailKite vs Loops

MailKite Loops
Product / lifecycle email API templates, no visual builder Excellent visual editor + loops
Transactional send from/to/subject/html + inReplyTo Template-based (transactionalId), free on paid plans
Inbound email (an agent's inbox) Parsed JSON webhook per address None — send-only
Read a verification code / reply text + html + threadId delivered Not possible without a second provider
SPF/DKIM/DMARC on inbound auth block on every message n/a (no inbound)
Reply threading inReplyTo threads the reply n/a (no inbound)
Run the agent for you Route action: 'agent' on a queue No
Per-domain fees None — unlimited domains Priced by subscribed contacts

Competitor capabilities change — we re-audit these tables regularly. Spot something out of date? Tell us and we'll fix it.

Show the payload

What actually hits your webhook

Loops' send side is clean, but the loop stops at 'delivered.' MailKite POSTs the reply back as parsed JSON so the agent can read it and answer.

Loops transactional send (outbound only)
http
// Loops: outbound only. This is the whole send side, and it's nice.
await fetch("https://app.loops.so/api/v1/transactional", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.LOOPS_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
transactionalId: "clfq6…", // a template you published in the Loops editor
email: "ada@example.com",
dataVariables: { code: "418207" }, // fills the template
}),
});

// …now the agent needs to READ ada's reply — or the code a service just mailed it.
// Loops has no endpoint for that. You add a second, receiving provider here.
MailKite
json
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=…" }
]
}
The price advantage

Unlimited domains. One quota. Free to start.

MailKite

  • Free: 3,000 emails/mo (in + out)
  • Unlimited domains on every plan
  • Pro $20/mo → 50,000, graceful overage

Loops

  • Priced by subscribed contacts, from ~$49/mo
  • Free tier ~4k sends / 1k contacts
  • Transactional sends free on paid plans

Different jobs, different meters: Loops bills by contacts for product email; MailKite bills one combined in + out volume and never charges per domain. Many teams keep both.

See full MailKite pricing →

Switch in an afternoon

Moving from Loops

  1. 1

    Keep Loops for product email

    Nothing to rip out — leave your onboarding, lifecycle loops, and transactional templates where they are. This adds the receiving half Loops doesn't cover.

  2. 2

    Point a domain at MailKite

    DNS-verify the domain (MX to receive, SPF + DKIM to send), pick an address like agent@myapp.ai, and set a webhook. No sandbox or approval wait.

  3. 3

    Handle the inbound event

    Verify x-mailkite-signature with verifyWebhook, read event.text / event.auth, and reply with mk.send() — or let a route with action: 'agent' run the loop for you.

Questions

Does Loops support inbound email?

No. Loops is send-only — marketing, lifecycle, and transactional outbound. Its 'incoming webhooks' receive events from platforms like Stripe and Clerk (not email), and its outbound webhooks report send-side events like delivered and bounced. There's no MX setup, no inbound parse, and no address that receives mail.

Should I stop using Loops?

Probably not, if you use it for product email — its editor and lifecycle loops are genuinely good. This is about a different job: giving an autonomous agent its own inbox. Many teams keep Loops for onboarding and add MailKite for the agent's receiving loop.

How does the agent read a verification code with MailKite?

Point a domain at MailKite, pick an address, and set a webhook. Inbound mail is parsed to JSON and POSTed as an email.received event with text, html, threadId, and an auth block — the agent reads the code directly and replies with mk.send().

Go deeper

The Loops alternative for AI agents →

The long-form take on our blog — receipts, runnable code, and where we won't overclaim.

Try MailKite free — keep Loops running until you're ready.

Point a domain, drop in a webhook URL, receive your first email. Unlimited domains, no credit card.