sendsend.email

Send an email

POST/v1/emails

Queues one message. A 202 means the message was durably queued, not delivered: follow its outcome with webhooks or by fetching it. Send either subject with html and/or text, or a template_id with variables, never both. Up to 50 recipients in total across to, cc and bcc. Live messages must come from a verified domain in the same project. Recipients on your suppression list are skipped.

Add up to 10 attachments (base64 content or an https path we download, with a content_id to show an image inline; up to 10 MB in total; executables and scripts are refused). Attachments are not available in a batch. Add up to 20 of your own headers (for example List-Unsubscribe); headers SendSend sets itself cannot be overridden.

Send an Idempotency-Key header so a retry can never deliver twice.

Required scope: emails:send

Parameters

NameInDescription
Idempotency-KeyoptionalheaderUp to 255 printable characters. The same key with the same body returns the original message; the same key with a different body returns 409. Kept for 24 hours.

Request body

FieldType
fromrequiredstring
tooptionalstring[]
ccoptionalstring[]
bccoptionalstring[]
reply_tooptionalstring[]
subjectoptionalstring
htmloptionalstring
textoptionalstring
template_idoptionalstring
template_versionoptionalinteger
variablesoptionalobject
languageoptionalstring
tagsoptionalobject
scheduled_atoptionalstring
attachmentsoptionalobject[]
headersoptionalobject

Unknown fields are rejected, so a typo never silently does nothing.

Example

curl -X POST 'https://api.sendsend.email/v1/emails' \
  -H "Authorization: Bearer $SENDSEND_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H 'Content-Type: application/json' \
  -d '{
  "from": "Acme <hello@mail.acme.com>",
  "to": [
    "maria@example.com"
  ],
  "subject": "Welcome to Acme",
  "html": "<p>Thanks for signing up!</p>",
  "text": "Thanks for signing up!",
  "tags": {
    "application_reference": "signup_123"
  }
}'

Response 202

{
  "id": "msg_8Xk2pQwLr0aVn3Zt",
  "object": "email",
  "environment": "live",
  "status": "queued",
  "status_reason": null,
  "simulated": false,
  "from": "Acme <hello@mail.acme.com>",
  "to": [
    "maria@example.com"
  ],
  "cc": [],
  "bcc": [],
  "reply_to": null,
  "subject": "Welcome to Acme",
  "template_id": null,
  "template_version": null,
  "tags": {
    "application_reference": "signup_123"
  },
  "provider_message_id": "0100019…",
  "request_id": "req_Kd83…",
  "attempts": 0,
  "recipients": [
    {
      "address": "maria@example.com",
      "kind": "to",
      "status": "queued"
    }
  ],
  "created_at": "2026-10-06T15:04:05.000Z",
  "updated_at": "2026-10-06T15:04:07.000Z"
}

Errors

StatusCodeWhen
400validation_errorThe request body or parameters are invalid. The message says which field.
401unauthorizedThe API key is missing, invalid or revoked.
403forbiddenThe key does not have the scope this endpoint needs.
422domain_not_verifiedThe From domain is not verified in this project.
400invalid_variablesA template variable is missing or has the wrong type.
422recipient_suppressedEvery recipient is on your suppression list.
409idempotency_conflictThe Idempotency-Key was used with a different request body.
429quota_exhaustedThe monthly allowance is used up and overage is off or capped.
429daily_limit_exceededThis project reached its daily sending limit.
403account_not_approvedLive sending waits for account approval. Test keys work meanwhile.
403account_suspendedThe account is paused. Contact support.
429rate_limitedToo many requests. Wait for the number of seconds in the Retry-After header.

Every error has the same shape. See Errors.