You POST. We deliver. You can prove it.

Calder is the email layer for apps that can’t afford “did they get it?” — OTPs, verification links, password resets, receipts. One endpoint, or plain SMTP if that’s your world. Honest statuses, and every event on the record.

No domain? No problem — start with Gmail, graduate when you grow.

202 Accepted in millisecondsRetry without double-sendingWebhooks that show their work
Ink illustration of a courier striding forward with a blue envelope
Carried, not wished.

How it works

Most email APIs are a black box with a prayer inside.

Here’s ours with the lid off: your request is validated, stored, and queued in milliseconds — then a worker walks the email to the provider and writes down everything that happens.

01 · You
Your application
One POST. Idempotency-Key header, Bearer API key.
02 · Calder API
Validate → persist → enqueue
Responds 202 Accepted. Nothing blocks on delivery.
03 · Worker
Send & retry
Backoff with jitter. Dead-letter, never silent loss.
04 · Provider
AWS SES
Behind an abstraction — swappable, failover-ready.
05 · Inbox
Delivered
Bounce and complaint signals flow back as events.
every step emits →email.queuedemail.sentemail.deliveredemail.bouncedsigned webhooks · retried with history

Two ways in

Use the interface you already know.

Modern app? POST JSON. Existing stack, WordPress, Laravel, cron scripts? Point your SMTP client at us. Either way there’s no mail server to run, no queue to babysit, no retries to implement — and delivery lands in the same observable pipeline.

api — POST /v1/emails → 202
POST /v1/emails → 202
{ "id": "em_9f2k41xq", "status": "queued" }
smtp — smtp.calder.click:587
host: smtp.calder.click
port: 587 (STARTTLS)
user: <project username>
pass: <generated secret>
→ 250 Queued (same pipeline)
you never operate →mail serversqueuesretrieswebhooksprovider infrabring a domain when ready — test keys need nothing

Start without a domain

Sixteen and learning Next.js? Send email today.

No domain to buy, no DNS to decipher, no SMTP server to babysit. Connect the Gmail account you already have — through Google’s own authorization, never your password — and send through the same API, logs, and events as everyone else. When the project grows up, verify a domain and graduate. Nothing rewrites.

gmail quickstart — same Calder API
$ curl https://api.calder.click/v1/emails \
  -H "Authorization: Bearer calder_sk_test_…" \
  -d '{"from":"myproject@gmail.com","to":"customer@example.com","subject":"Welcome!","html":"<h1>Welcome!</h1>"}'

// SDKs (npm install calder) land with v1 — the API above is stable now.

How you start

Connect Gmail — OAuth, two clicks, capped for developmentno domain
Or verify a domain — DNS records, full production capacityproduction
Graduate anytime — same key, same code, new transportno rewrite

Gmail sending is capped and rate-limited on purpose — it’s the on-ramp, not bulk infrastructure. Limits are always visible before you hit them. Full walkthrough: Gmail Quickstart →

No domain →Connect Gmail→ build → grow →Verify domain→ production infrastructure. Same key throughout.

Developer experience

Your first delivery in about five minutes.

No sales call, no credit card, no DNS homework to start. Test keys simulate the whole pipeline — queue, provider, events, webhooks — without a single real inbox involved.

  1. 01Grab a test key. Prefixed, revocable, hashed at rest. Lives in your .env in seconds.
  2. 02POST your email. Get a 202 back in milliseconds with an id you can track forever.
  3. 03Watch the webhook land. Signed, retried, and inspectable — proof of delivery, not vibes.
request.sh — send an email
$ curl https://api.calder.click/v1/emails \
  -H "Authorization: Bearer calder_sk_live_…" \
  -H "Idempotency-Key: welcome-user-4815" \
  -d '{
    "from": "app@acme.com",
    "to": "ada@example.com",
    "subject": "Verify your email",
    "html": "<p>Your code…</p>"
  }'
202 Accepted → webhook event
// 202 Accepted
{
  "id": "em_9f2k41xq",
  "status": "queued"
}

// …moments later, your webhook receives:
{
  "event": "email.delivered",
  "data": { "email_id": "em_9f2k41xq" }
}
Errors — { error: { code, message, request_id } }Keys — calder_sk_test_… never leaves the sandbox

Why Calder

Sending an email is easy. Sending it exactly once, knowing it arrived, and proving it later — that’s the actual job.

01 — Async by default

Your API never waits on a mail server

Providers throttle, networks stall — that’s not your request’s problem. We persist, queue, and answer in milliseconds; delivery happens somewhere built to wait around.

receipt@example.comdelivered1.02s
otp@example.comsending
retry@example.comretry 2/5+4s
bounce@example.combounced0.61s
02 — Idempotent sends

Nobody gets two receipts

Your request timed out. Did it send or not? Hand us an Idempotency-Key and a retry returns the exact same result — same key, same outcome, one email.

Idempotency-Key: welcome-user-4815
POST →
202 · created em_9f2k41xq, result stored
POST ↻
200 · same key → original result replayed
emails sent
exactly one — that’s the whole point
03 — Events & webhooks

Webhooks that show their work

A webhook that fires once into the void isn’t infrastructure — it’s a wish. Every send fans out signed, retryable events you can actually inspect.

email.queued → your-url/hook20041ms
email.sent → your-url/hook20038ms
email.delivered → your-url/hook20044ms
email.bounced → your-url/hookretry 1
04 — Observability

“I never got the email.” Now you have an answer.

Every response carries a request ID. Every email gets a timeline from creation to open.

em_9f2k41xq · req_x7k2… · project acme/production
createdvalidated · suppression checked · persistedt+0ms
queuedjob accepted · worker picked upt+12ms
sentprovider accepted · MessageId ses_84…t+340ms
deliveredinbox confirmedt+1.02s
openedfirst open recordedt+4m
05 — Domains & reputation

Your domain, verified. Your reputation, visible.

An email from you@yourproduct.com lands differently than one from a shared sending service — in the inbox and in the reader’s head. Verify with DNS, then watch what it earns you.

Domain under protection

The signal

Every send emits a lifecycle. Every lifecycle is observable.

queued → sent → delivered → opened → clicked · bounced · complained · failed

The product

Everything in the box, nothing you have to glue together.

Providers, DNS, queues, retries, webhooks, suppression, billing — the fragmented mess scattered across providers, DNS consoles, queues you built yourself, and billing spreadsheets — already assembled into one dashboard and one API.

Projects & environments

One account, every app and stage

Organize sending by organization, then split into projects — production, staging, that side-project. Test keys behave exactly like live ones except nothing ever leaves the building.

  • Separate test and live API keys per project
  • Per-project logs, events, and rate limits
  • Revoke and rotate keys without touching code
acme / productionlive42k/mo
acme / stagingtest1.2k/mo
side-projectlive300/mo
keys
calder_sk_test_… · calder_sk_live_… — hashed, revocable
isolation
every query scoped to its project, always
Sending setup

Your name on every send

Paste three DNS records, wait for propagation, done — no redeploy required.

Domain under protection
Templates soon

Emails your designer would sign off on

Versioned templates with variables, previews, and publishing — so “can you tweak the receipt?” stops meaning a code deploy. We’re building this right after the delivery core is bulletproof.

  • Variables like {{ first_name }} with safe defaults
  • Version history and one-click rollback
  • Test sends before anything goes live
Template blocks
Usage & billing

Know what it costs before finance asks

Every send is metered from the same durable records as everything else — not a counter that drifts. Watch usage climb toward your plan in real time, in naira or dollars, with hard limits instead of surprise overages.

  • Live usage against plan quotas
  • Invoices that match your dashboard, always
  • NGN and USD plans with receipts included
Metered usage

Pricing · hypothesis, not promise

Priced for where you build.

Naira-first plans a Nigerian builder can actually pay — no per-seat arithmetic, no overage traps. Usage is metered from the same durable records as everything else, so the invoice always matches your dashboard. Final numbers lock after our unit-economics review.

Free
₦0 / mo
$0 in USD

3,000 emails / mo

  • Gmail connection for beginners
  • 1 custom domain
  • API + SMTP + SDK
  • Templates + basic logs + 1 webhook
Start free
Builder
≈ ₦3,500 / mo
TBD in USD

~25,000 emails / mo

  • Everything in Free
  • 5 domains + campaigns
  • Multiple webhooks
  • Better retention
Choose Builder
Pro
≈ ₦7,500 / mo
TBD in USD

~75,000 emails / mo

  • Everything in Builder
  • 20 domains + improved analytics
  • Larger retention
  • Team functionality
Choose Pro
Scale
≈ ₦20,000 / mo
TBD in USD

~250,000 emails / mo

  • Everything in Pro
  • Significantly higher limits
  • Advanced analytics
  • Priority support
Talk to us

Hypothesis under unit-economics review (docs/PRICING.md) — locked plans publish at launch. Hard limits, no surprise overages. USD equivalents set at launch parity.

Get started

Go get your first delivery.

Not your first signup form, not your first dashboard tour — your first email, landing in an inbox, with the webhook to prove it. Test keys are free and can’t hurt anything. The only thing standing between you and that little delivered tag is one POST request.