Quickstart: curl / any language
The whole API is plain JSON over HTTPS with bearer auth. If your language can curl, it can send.
Facts verified 2026-07-17 — corrections: hello@emailfast.dev
Send
curl https://api.emailfast.dev/v1/emails \
-H "Authorization: Bearer ef_sandbox_..." \
-H "Content-Type: application/json" \
-d '{
"to": "ada@example.com",
"to_name": "Ada",
"subject": "Welcome!",
"html": "<h1>Hi {{name}}</h1>",
"data": { "name": "Ada" },
"message_stream": "transactional",
"idempotency_key": "signup-42"
}'{ "id": "msg_01j…", "status": "queued", "idempotent_replay": false }a 202 from the API means the send is committed to a durable, partitioned outbox before we answer — a crash can't lose it, and a retry with the same idempotency key can't double-send.
Read the timeline
curl https://api.emailfast.dev/v1/messages/msg_01j… \
-H "Authorization: Bearer ef_sandbox_..."Returns the message plus its full event history — admitted, rendered, delivered, opened (human opens only: open tracking that refuses to lie: privacy-proxy prefetch “opens” are detected and not counted as human reads).
Batch
curl https://api.emailfast.dev/v1/emails/batch \
-H "Authorization: Bearer ef_sandbox_..." \
-d '{ "messages": [ { "to": "a@example.com", "subject": "…", "html": "…" },
{ "to": "b@example.com", "subject": "…", "html": "…" } ] }'Up to 500 per call, per-item results, per-recipient idempotency.
Suppressions
curl https://api.emailfast.dev/v1/suppressions \
-H "Authorization: Bearer ef_sandbox_..."Suppression is enforced at admission for every ingress — every send — REST, SMTP, browser SDK, compatibility endpoints, broadcasts, automations — passes through one admission gate: idempotency, suppression, quota, and content policy in a single checkpoint no ingress can skip.
Everything else
The complete surface — templates, contacts, broadcasts, journeys, webhooks, validation — is in the OpenAPI spec. Every endpoint follows the same conventions you just used.