Everything between your app and the inbox.
Sending, domain setup, events, webhooks and the safety rails around them, operated for you.
What happens to one email.
POST /v1/emails with a server-side key.202.Sending that survives retries.
You get an email id only after the email is stored. If it cannot be stored, you get a retryable 503, never a made-up id.
- Single emails, or batches of up to 100 per request
- Scheduling from 1 minute to 30 days ahead, with cancel and reschedule
- Up to 50 recipients per email
- Attachments up to 15 MB each and 40 MB per message on paid plans
Idempotency-Keykept for at least 24 hours
curl -X POST https://api.outstamp.dev/v1/emails \
-H "Authorization: Bearer $OUTSTAMP_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: welcome-42" \
-d '{
"from": "Acme <[email protected]>",
"to": "[email protected]",
"subject": "Welcome to Acme",
"html": "<p>Your account is ready.</p>"
}'const response = await fetch("https://api.outstamp.dev/v1/emails", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OUTSTAMP_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": `welcome-${user.id}`
},
body: JSON.stringify({
from: "Acme <[email protected]>",
to: "[email protected]",
subject: "Welcome to Acme",
html: "<p>Your account is ready.</p>"
})
});
const email = await response.json(); // 202, { id, status: queued }import os, requests
response = requests.post(
"https://api.outstamp.dev/v1/emails",
headers={
"Authorization": f"Bearer {os.environ['OUTSTAMP_API_KEY']}",
"Idempotency-Key": f"welcome-{user.id}",
},
json={
"from": "Acme <[email protected]>",
"to": "[email protected]",
"subject": "Welcome to Acme",
"html": "<p>Your account is ready.</p>",
},
)
email = response.json() # 202, { id, status: queued }Domains, set up with you.
We show the exact records, check them for you and tell you what is missing.
- Three DKIM records are required; MAIL FROM and DMARC are recommended
- A domain with DKIM alone can already send, marked as partially verified
- Automatic checks for 72 hours, then regular re-checks
- Notes for Cloudflare, Route 53, Namecheap and GoDaddy
| CNAME | DKIM | Verified |
| CNAME | DKIM | Verified |
| CNAME | DKIM | Verified |
| MX | MAIL FROM | Verified |
| TXT | SPF | Verified |
| TXT | DMARC | Recommended |
Events you can build on.
Submission, delivery and complaints are separate facts, so a late event never overwrites a newer one.
- HMAC-SHA256 signature over the delivery id, the timestamp and the raw body
- 10 delivery attempts over 48 hours, and replay for 30 days
- At least once and unordered by design: deduplicate on the event id
- When you rotate the secret, deliveries carry both signatures for 24 hours
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(request, rawBody, secret) {
const id = request.headers["outstamp-id"];
const timestamp = request.headers["outstamp-timestamp"];
const header = request.headers["outstamp-signature"] ?? "";
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const expected = createHmac("sha256", secret)
.update(`${id}.${timestamp}.${rawBody}`)
.digest("hex");
return header.split(",")
.map((part) => part.trim().replace(/^v1=/, ""))
.some((candidate) => candidate.length === expected.length &&
timingSafeEqual(Buffer.from(candidate, "hex"), Buffer.from(expected, "hex")));
}Event types you can subscribe to
- email.accepted
- email.scheduled
- email.queued
- email.sent
- email.delivered
- email.delivery_delayed
- email.bounced
- email.complained
- email.rejected
- email.failed
- email.suppressed
- email.opened
- email.clicked
- email.canceled
- email.submission_unknown
- domain.created
- domain.status_changed
- domain.deleted
- suppression.created
- suppression.deleted
- project.quota_warning
- project.reputation_warning
- project.sending_paused
- project.sending_resumed
Test and live, kept apart.
Different keys, different prefixes, and test mail that never reaches the internet.
os_test_andos_live_keys you can tell apart at a glance- Simulator addresses for delivery, bounce, delay, complaint, suppression, rejection, failure and a lost response
- Test sends produce the same events and webhooks as live ones, and are never billed
- Before your domain is ready, real emails to verified members of your workspace, 10 a day
| Send to | You get |
|---|---|
| delivered@simulator.outstamp.dev | email.delivered |
| bounce@simulator.outstamp.dev | email.bounced |
| transient@simulator.outstamp.dev | email.delivery_delayed |
| complaint@simulator.outstamp.dev | email.complained |
| suppressed@simulator.outstamp.dev | email.suppressed |
Safety rails, on by default.
The checks a careful email operator would run, applied to every project.
- Hard bounces and complaints are suppressed automatically
- Bounce rate: a warning at 3%, action at 5%. Complaint rate: a warning at 0.05%, action at 0.1%
- Sending limits grow with your delivery history
- Suppressed addresses are checked before every send
- Sending
Acme app
Bounce rate 0.4% in 24 hours
- Sending
Acme staging
Bounce rate 0.1% in 24 hours
- Paused
Side project
Bounce rate 5.2% in 24 hours
A dashboard for the whole team.
What developers, support and finance each need, without sharing one login.
Email log
Find any email and see its full timeline, recipients and content while retention allows.
Domains and keys
DNS status per record, and keys limited by permission and by domain.
Webhooks
Every delivery attempt with its response, a test button and replay.
Suppressions
Why an address is blocked, and a way to remove it, with a confirmation.
Usage
Emails and recipients per day, against your plan and limits.
Team and security
Owner, admin, developer, analyst and billing roles, with passkeys and authenticator apps.
Your data, kept briefly.
Shorter retention is a setting, not a paid extra.
| Data | Kept for | Can be set to |
|---|---|---|
| Delivery metadata and events | 30 days | Fixed |
| Recipient addresses and subject | 30 days | 0, 1, 7 or 30 days |
| HTML and text bodies | 7 days | 0, 1, 7 or 30 days |
| Attachments | Until delivery, plus up to 24 h | Deleted right after submission |
| API request bodies | 7 days | Off |
| Webhook events and attempts | 30 days | Fixed |
- No model training on your emails, and no advertising
- Support access to content is audited, and you can turn it off
- Turning off content storage costs nothing
Not here yet.
So you can decide before you sign up, not after.
Templates
Send the HTML and text you render. Stored templates are not available yet.
SMTP relay
Outstamp is an HTTP API. There is no SMTP endpoint yet.
Official SDKs
Plain REST with an OpenAPI schema: any HTTP client works.
Send your first email in test mode.
No card and no DNS. Add your domain when you are ready.
- No card needed to test
- Prices in euros, excluding VAT