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.

POSThttps://api.sndr.sh/api/cranl/v1/send
Send email
curl -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" }
  }'
202Accepted
{
  "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

Authorizationstringheaderrequired

Bearer followed by an access token. Needs the send scope.

Body

application/json
fromstringrequired

Sender, as an address or "Name <address>". Its domain must be added and verified on the connected account.

tostring[]required

Recipient 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.

subjectstring

Subject line, single line, max 998 bytes. Required unless the template provides one.

htmlstring

HTML body. Send html, text or both, unless template_id provides them.

textstring

Plain-text body.

reply_tostring

Reply-To address.

template_idstring

Saved template ID (tpl_...). Its subject, html and text fill any of those fields you leave empty.

variablesobject

Values for {{ name }} placeholders in subject, html and text, e.g. {"first_name":"Alex"}. {{ user.name }} reads nested objects; unknown placeholders are left as is.

headersobject

Extra 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

401unauthenticatedMissing or invalid Bearer token.
401token_expiredAccess token expired — exchange the refresh token for a new pair.
401token_revokedToken was explicitly revoked.
400invalid_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.
400suppressedEvery to address is on the suppression list. Suppressed cc/bcc addresses are dropped silently.
402quota_exceededThe monthly email quota is used up. It resets on the 1st of the month (UTC).
403insufficient_scopeToken is missing the send scope.
403domain_not_linkedThe from domain has not been added to the connected account.
403domain_not_verifiedThe from domain is added but its DNS records are not verified yet.
403quarantine_activeSending is paused for this account. Contact SNDR support.
403forbiddenA recipient is on a known spam-trap list. Remove it and retry.
413payload_too_largeThe request, or the rendered html + text, is over 16 MiB.
429send_velocitySending too fast for this account. Back off and retry.
503sends_frozenSending is temporarily paused platform-wide. Retry later.