API reference
Send email
Queue a single email for delivery.
Why use this
For example
A customer checks out in your shop. Your server makes one call to send, and they get their order confirmation — from your own address, tracked end to end.
Example
import { YourMail } from "yourmail";
const yourmail = new YourMail(process.env.YOURMAIL_API_KEY!, {
baseUrl: process.env.YOURMAIL_BASE_URL!,
});
const { id } = await yourmail.send({
from: "hello@mail.acme.com",
to: ["alice@example.com"],
cc: ["bob@example.com"],
bcc: ["archive@acme.com"],
replyTo: "support@acme.com",
subject: "Welcome to Acme",
html: "<h1>Hello Alice</h1>",
text: "Hello Alice",
attachments: [
{
filename: "invoice.pdf",
content: "<base64-encoded content>",
contentType: "application/pdf",
},
],
tags: [{ name: "category", value: "welcome" }],
idempotencyKey: "welcome-usr_123",
headers: {
"List-Unsubscribe": "<mailto:unsub@acme.com>",
"X-Campaign-ID": "launch-2026",
},
});
console.log(id);const res = await fetch(
"https://api.yourmail.dev/v1/emails",
{
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
from: "hello@mail.acme.com",
to: ["alice@example.com"],
cc: ["bob@example.com"],
bcc: ["archive@acme.com"],
replyTo: "support@acme.com",
subject: "Welcome to Acme",
html: "<h1>Hello Alice</h1>",
text: "Hello Alice",
attachments: [
{
filename: "invoice.pdf",
content: "<base64-encoded content>",
contentType: "application/pdf",
},
],
tags: [{ name: "category", value: "welcome" }],
idempotencyKey: "welcome-usr_123",
headers: {
"List-Unsubscribe": "<mailto:unsub@acme.com>",
"X-Campaign-ID": "launch-2026",
},
}),
}
);
const { id } = await res.json();curl -X POST https://api.yourmail.dev/v1/emails \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "hello@mail.acme.com",
"to": ["alice@example.com"],
"subject": "Welcome to Acme",
"html": "<h1>Hello Alice</h1>"
}'Request body
All fields are JSON. from, to, subject, and at least one of html / text are required.
fromstring- RequiredA bare address (hello@mail.acme.com) or one with a display name (Acme Support <hello@mail.acme.com>) — the display name is what the recipient's inbox shows. Names containing a comma or dot are quoted for you. Must be on a verified domain you own — the one exception is no-reply@yourmail.dev, the shared sandbox sender, which puts the send in test mode instead. Ownership is checked against the address, never the display name.
tostring | string[]- RequiredOne or more recipient addresses, each with an optional display name. Combined with cc + bcc: max 50 total. In test mode (from: no-reply@yourmail.dev) any recipient other than your signup email or an SES simulator address is silently rewritten to your signup inbox (cc/bcc dropped), not rejected — you may omit to entirely and it defaults to your own inbox.
ccstring | string[]- OptionalCarbon-copy recipients, display names allowed. Counts toward the 50-recipient cap.
bccstring | string[]- OptionalBlind-copy recipients, display names allowed. Counts toward the 50-recipient cap.
replyTostring- OptionalReply-To address, display name allowed. Must be a valid email.
subjectstring- RequiredNon-empty string.
htmlstring- ConditionalHTML body. At least one of html or text is required. Combined html + text must be under 1 MB (UTF-8 bytes).
textstring- ConditionalPlain-text body. At least one of html or text is required.
attachmentsAttachment[]- OptionalMax 20 files. Each file: max 10 MB decoded. Total: max 25 MB decoded. Each item needs filename (string) and content (base64 string); contentType defaults to application/octet-stream.
tagsTag[]- OptionalMax 10 tags. Each tag is { name: string; value: string }. Used for filtering and analytics.
idempotencyKeystring- OptionalIf a send with this key was already queued, the original id is returned without re-sending. Safe to retry on network failures.
headersobject- OptionalCustom mail headers as a string→string object. Max 10 headers; each name max 64 chars; each value max 1 KB; combined total max 4 KB. Reserved headers (From, To, Subject, Content-Type, DKIM-Signature, etc.) are rejected.
bulkboolean- OptionalMarks the send as bulk (newsletters, announcements) rather than transactional. Requires exactly one `to` recipient and no cc/bcc — anything else is a 400. On a live send we inject one-click List-Unsubscribe headers so mailbox providers show an unsubscribe button, unless you set those headers yourself (test-mode sends go to your own inbox, so they get none). Recipients who unsubscribe are blocked from bulk mail only; your transactional email still reaches them. Defaults to false.
Response
On success the API returns HTTP 200 with the new email ID.
// 200 OK
{ "id": "jn7abc123def456" }Errors
All errors follow the shape { error: { type, message } }. See Errors for the full reference. Common errors for this endpoint:
validation_errorMissing or invalid field (from, to, subject, html/text)
authentication_errorAPI key missing, malformed, or not recognised
domain_errorSending domain not verified or not owned by this account
validation_errorBody exceeds 1 MB, or attachment exceeds 10 MB / 25 MB total
suppressed_recipientRecipient is on this account's suppression list
sandbox_recipientTest mode only, and rare: a disallowed recipient is normally rewritten to your signup inbox rather than rejected — this fires only when your account has no signup email on file to rewrite to
rate_limitedPer-second burst exceeded — Retry-After header tells you when to retry
quota_exceededDaily or monthly send quota exhausted