API reference
The sending endpoint, its fields, its errors, and the limits that apply to it.
Base URL
https://app.getoutsend.com/api/v1
Authentication
Every request carries a bearer token:
Authorization: Bearer outsend_live_…
Keys are scoped to a workspace, or narrowed to a single domain. A request with a missing
or unknown key returns 401 with {"error": "Invalid or missing API key"}.
Send an email
POST /emails
Fields
| Field | Type | Required | Notes |
|---|---|---|---|
from | string | yes | Must be on a verified domain in your workspace. |
to | string or array | yes | One or many recipients. |
subject | string | yes | |
html | string | — | HTML body. |
text | string | — | Plain-text body. Send both when you can. |
cc | string or array | — | |
bcc | string or array | — | |
replyTo | string or array | — | Also accepted as reply_to. |
headers | object | — | Custom headers. |
scheduled_at | ISO 8601 | — | Send later instead of now. |
stream | string | — | transactional (default) or broadcast. |
At least one of html or text should be present for a message anyone can read.
Idempotency
Idempotency-Key: password-reset-8f21c4
The response for a given key is cached for 24 hours. Retrying with the same key returns the original result instead of sending again — which means your retry logic can be as aggressive as it needs to be without duplicating mail.
Response
{ "id": 10482, "stream": "transactional" }
201 Created. The id is what you use to look up the message and its events.
Errors
| Status | Meaning |
|---|---|
401 | Invalid or missing API key. |
422 | Validation failed — an unverified from domain, a missing field, a malformed address. The message says which. |
429 | Rate limited. See below. |
Errors are returned as {"error": "…"} with a sentence meant for a human, not a code you
have to look up.
Rate limits
| Window | Limit |
|---|---|
| Per minute | 60 requests per key |
| Per hour | 1,000 requests per key |
Exceeding either returns 429 with a plain message. We would rather reject a request
loudly than accept it and quietly drop the mail. Limits can be raised on Scale and
Dedicated plans.
Streams
Every message belongs to a stream, and each stream keeps its own suppression list.
transactional— password resets, receipts, notifications. The default.broadcast— campaigns and anything list-based.
Keeping them separate means someone unsubscribing from your newsletter does not stop their password reset from arriving, which is the failure mode this design exists to prevent.
Suppression
Addresses land on a suppression list after a permanent bounce, a complaint, or an
unsubscribe. Sends to a suppressed address are recorded with status suppressed rather
than being attempted — they are visible in the log and are not billed.