Emails
Send email
Queue an email for delivery. Returns 202 Accepted with the queued Email. Send an Idempotency-Key header to make retries safe: a repeat with the same key within 24 hours returns the first response.
https://api.sndr.sh/api/cranl/v1/sendcurl -X POST 'https://api.sndr.sh/api/cranl/v1/send' \
-H 'Authorization: Bearer sndr_your_access_token' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: order-1234-confirmation' \
-d '{
"from": "Acme <noreply@acme.com>",
"to": ["customer@example.com"],
"reply_to": "support@acme.com",
"subject": "Your order #{{ order_id }} is confirmed",
"html": "<h1>Thanks, {{ first_name }}!</h1><p>Order #{{ order_id }} is being prepared.</p>",
"text": "Thanks, {{ first_name }}! Order #{{ order_id }} is being prepared.",
"variables": { "first_name": "Alex", "order_id": "1234" }
}'{
"id": "em_3f9c1a2b-7d4",
"organization_id": "org_8d41c7a2-3f6",
"from": "\"Acme\" <noreply@acme.com>",
"to": ["customer@example.com"],
"subject": "Your order #1234 is confirmed",
"status": "queued",
"domain_id": "dom_a7c2e910-4b1",
"created_at": "2026-06-01T12:00:00Z"
}Authorization
AuthorizationstringheaderrequiredBearer followed by an access token. Needs the send scope.
Body
application/jsonfromstringrequiredSender, as an address or "Name <address>". Its domain must be added and verified on the connected account.
tostring[]requiredRecipient addresses, 1–1000, plain format (no display names). Must be an array, even for one recipient.
ccstring[]CC addresses, max 100.
bccstring[]BCC addresses, max 100. to + cc + bcc together may not exceed 1000.
subjectstringSubject line, single line, max 998 bytes. Required unless the template provides one.
htmlstringHTML body. Send html, text or both, unless template_id provides them.
textstringPlain-text body.
reply_tostringReply-To address.
template_idstringSaved template ID (tpl_...). Its subject, html and text fill any of those fields you leave empty.
variablesobjectValues for {{ name }} placeholders in subject, html and text, e.g. {"first_name":"Alex"}. {{ user.name }} reads nested objects; unknown placeholders are left as is.
headersobjectExtra headers as string pairs, e.g. {"X-Entity-Ref-ID":"1234"}. No CR/LF allowed; standard headers such as From, To, Subject, Reply-To or List-Unsubscribe are ignored.
tagsobject[]Objects with string values, e.g. [{"name":"category","value":"welcome"}]. Accepted but not stored or returned yet.
attachmentsobject[]Up to 10 files as {filename, content, content_type?}. content is standard base64; content_type defaults to application/octet-stream. Max 10 MiB decoded in total; the whole request max 16 MiB.
Errors
unauthenticatedMissing or invalid Bearer token.token_expiredAccess token expired — exchange the refresh token for a new pair.token_revokedToken was explicitly revoked.invalid_requestBody failed validation — e.g. to sent as a string, an invalid address, no subject or body, over 1000 recipients, CR/LF in a header field, unknown template_id, or a bad attachment.suppressedEvery to address is on the suppression list. Suppressed cc/bcc addresses are dropped silently.quota_exceededThe monthly email quota is used up. It resets on the 1st of the month (UTC).insufficient_scopeToken is missing the send scope.domain_not_linkedThe from domain has not been added to the connected account.domain_not_verifiedThe from domain is added but its DNS records are not verified yet.quarantine_activeSending is paused for this account. Contact SNDR support.forbiddenA recipient is on a known spam-trap list. Remove it and retry.payload_too_largeThe request, or the rendered html + text, is over 16 MiB.send_velocitySending too fast for this account. Back off and retry.sends_frozenSending is temporarily paused platform-wide. Retry later.