Skip to content
spacepost

Illustration: email going from an app, through SpacePost on Amazon SES in Frankfurt (eu-central-1), to an inbox.

Resend-compatible API · Built on Amazon SES

Keep your Resend code. Change one line.

SpacePost implements the Resend API on Amazon SES. Point the official SDK at a new base URL and keep the rest: sends, batches, webhooks, domains. Run by an EU company.

Free for 3,000 emails a month, no card. Pro €9/month for 50,000 (excl. VAT).

Send an email with SpacePost

Compare base URL with Resend
import { Resend } from "resend";

const resend = new Resend(
  process.env.SPACEPOST_API_KEY,
  { baseUrl: "https://api.spacepost.dev" },
);

const { data, error } = await resend.emails.send({
  from: "Acme <onboarding@test.spacepost.dev>",
  to: ["delivered@test.spacepost.dev"],
  subject: "Hello from SpacePost",
  html: "<p>It works.</p>",
});
import { Resend } from "resend";

const resend = new Resend(
  process.env.RESEND_API_KEY,
  { baseUrl: "https://api.resend.com" },
);

const { data, error } = await resend.emails.send({
  from: "Acme <onboarding@test.spacepost.dev>",
  to: ["delivered@test.spacepost.dev"],
  subject: "Hello from SpacePost",
  html: "<p>It works.</p>",
});

{ data: { id: "0192f3a4-7c1e-7b6d-9a35-2f0e6f1d8c10" }, error: null }

// npm install @spacepost/node
import { SpacePost } from "@spacepost/node";

const spacepost = new SpacePost(process.env.SPACEPOST_API_KEY);

const { data, error } = await spacepost.emails.send({
  from: "Acme <onboarding@test.spacepost.dev>",
  to: ["delivered@test.spacepost.dev"],
  subject: "Hello from SpacePost",
  html: "<p>It works.</p>",
});

{ data: { id: "0192f3a4-7c1e-7b6d-9a35-2f0e6f1d8c10" }, error: null }

curl -X POST https://api.spacepost.dev/emails \
  -H "Authorization: Bearer $SPACEPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <onboarding@test.spacepost.dev>",
    "to": ["delivered@test.spacepost.dev"],
    "subject": "Hello from SpacePost",
    "html": "<p>It works.</p>"
  }'

{"id":"0192f3a4-7c1e-7b6d-9a35-2f0e6f1d8c10"}

import nodemailer from "nodemailer";

const smtp = nodemailer.createTransport({
  host: "smtp.spacepost.dev",
  port: 25976,
  requireTLS: true, // STARTTLS
  auth: { user: "spacepost", pass: process.env.SPACEPOST_API_KEY },
});

await smtp.sendMail({
  from: "Acme <onboarding@test.spacepost.dev>",
  to: "delivered@test.spacepost.dev",
  subject: "Hello from SpacePost",
  html: "<p>It works.</p>",
});

250 OK: queued as 0192f3a4-7c1e-7b6d-9a35-2f0e6f1d8c10

# Claude Code: add the hosted MCP server
claude mcp add --transport http spacepost https://api.spacepost.dev/mcp \
  --header "Authorization: Bearer $SPACEPOST_API_KEY"

# Or run it locally over stdio
claude mcp add spacepost -e SPACEPOST_API_KEY=$SPACEPOST_API_KEY \
  -- npx -y @spacepost/mcp

Webhook events

  1. email.sent
  2. email.delivered

Simulated with a test address. No email is sent.

Only the base URL and API key change. Last tested with resend@6.35.0 on 29 Oct 2026.

Use the tools you already have

The Resend SDK, our own SDK, plain HTTP, SMTP or an agent over MCP. Pick one and send.

  1. Create an API key.
  2. Send a test email. No domain needed.
  3. Verify your domain with three DKIM CNAMEs.
Read the quickstart

See what happens to every email

Delivered, opened, clicked or bounced: each event reaches your webhook, signed and ready to verify.

  • email.sent
  • email.delivered
  • email.delivery_delayed
  • email.bounced
  • email.complained
  • email.opened
  • email.clicked
  • email.failed
  • email.scheduled
verify webhooks
import { Webhook } from "standardwebhooks";

const wh = new Webhook(process.env.SPACEPOST_WEBHOOK_SECRET!);
const event = wh.verify(rawBody, {
  "webhook-id": req.headers["webhook-id"],
  "webhook-timestamp": req.headers["webhook-timestamp"],
  "webhook-signature": req.headers["webhook-signature"],
});

Deliverability, handled

Grown out of the Amazon SES setup behind Space Invoices and our other products, which sent over 2.5 million emails in the past year.

Amazon SES underneath
Your mail goes out through Amazon SES, and you never touch the AWS console.
Your own reputation
If one sender's list goes bad, that sender is paused, not you.
Automatic suppression
Addresses that bounce or complain are skipped from then on.
Automatic pausing
If a list goes bad, sending pauses before your reputation takes the hit.
How we keep mail safe

Start free. Pay by the thousand when you grow.

48,000Pro€9/moexcl. VAT

Free

€0 /mo

excl. VAT

3,000 emails included.

Pro

€9 /mo

excl. VAT

50,000 emails included, then €0.25 per 1,000.

Scale

€35 /mo

excl. VAT

200,000 emails included, then €0.20 per 1,000.

See all pricing details

Questions, answered plainly

Something missing? Write to support@spacepost.dev.

Is it really compatible with Resend?
For sending, yes. Paths, payloads and errors match Resend's API, so most apps only change the base URL and the key. The comparison shows what's still on the way.
How is pricing calculated?
Paid plans include a set number of emails a month, then a fixed rate per extra 1,000. Free covers 3,000 a month and stops there. Pro is €9 for 50,000, Scale €35 for 200,000 (excl. VAT). No seats or per-domain fees. Coming from Resend? See the side-by-side.
Where is my data?
Email goes out through Amazon SES in Frankfurt, and the app and its database run in the EU. Payments are handled by Stripe in the EU and US, and GitHub sign-in is optional. Every customer gets a GDPR data processing agreement, and every provider is listed on our sub-processor page.
Can I send marketing email?
Yes, to people who opted in. Broadcasts add one-click unsubscribe for you. Bought or scraped lists aren't allowed.

Send your first email in two minutes

Create a free account, copy an API key and send to the test address. No domain, no credit card.

terminal
$ npm install @spacepost/node
$ export SPACEPOST_API_KEY=sp_live_…
$ node send.mjs
{ data: { id: "0192f3a4-7c1e…" }, error: null }