Sendr Docs
API Reference

Emails

Send transactional and marketing emails via the REST API.

Base URL

https://api.sendr.dev/v1

All endpoints require Authorization: Bearer <api_key>.


Send email

POST /v1/emails

Requires sending_access scope.

Request body

FieldTypeRequiredDescription
fromstringYesSender address. Format: Name <email@domain.com> or email@domain.com. Domain must be verified.
tostring | string[]YesRecipient(s). Up to 50 addresses.
subjectstringYesEmail subject line.
htmlstringNo*HTML body. Max 5 MB. At least one of html or text is required (unless using template_id).
textstringNo*Plain-text body. Max 1 MB.
ccstring | string[]NoCC recipients.
bccstring | string[]NoBCC recipients.
reply_tostringNoReply-to address.
attachmentsAttachment[]NoBase64-encoded file attachments.
tagsTag[]NoCustom key/value tags for filtering in analytics.
headersRecord<string, string>NoCustom email headers (e.g., X-* headers).
scheduled_atstring (ISO 8601)NoSchedule delivery for a future time. Must be in the future, max 1 year ahead.
template_idstringNoUse a saved template. Overrides html/text.
variablesRecord<string, any>NoTemplate substitution variables.
trackingbooleanNoEnable open/click tracking. Default true.

Attachment object:

{
  filename: string;       // e.g., "invoice.pdf"
  content: string;        // Base64-encoded file content
  content_type?: string;  // MIME type, default "application/octet-stream"
}

Tag object:

{
  name: string;   // e.g., "category"
  value: string;  // e.g., "welcome"
}

Example request

curl -X POST https://api.sendr.dev/v1/emails \
  -H "Authorization: Bearer $SENDR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <hello@acme.com>",
    "to": "user@example.com",
    "subject": "Welcome to Acme!",
    "html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
    "tags": [{"name": "category", "value": "welcome"}]
  }'

Response

{
  "id": "em_abc123",
  "from": "Acme <hello@acme.com>",
  "to": ["user@example.com"],
  "subject": "Welcome to Acme!",
  "status": "queued",
  "created_at": "2025-03-12T09:00:00Z"
}

Send marketing email

POST /v1/emails/marketing

Requires sending_access scope. Marketing emails automatically include List-Unsubscribe and List-Unsubscribe-Post headers for CAN-SPAM compliance.

Request body

Same as Send email, plus:

FieldTypeRequiredDescription
unsubscribe_urlstringYesURL added to List-Unsubscribe header. Required for CAN-SPAM.
list_idstringNoMailing list identifier used for list-level unsubscribe tracking.

Send batch

POST /v1/emails/batch

Requires sending_access scope. Send up to 100 emails in a single request. All emails are queued atomically.

Request body

FieldTypeRequiredDescription
emailsEmailItem[]YesArray of 1–100 email objects.
fromstringNoDefault sender address for all emails (can be overridden per-email).
subjectstringNoDefault subject for all emails (can be overridden per-email).
template_idstringNoDefault template for all emails.

Each item in emails accepts all send fields except from, subject, and template_id at the top level can serve as defaults.

Example request

curl -X POST https://api.sendr.dev/v1/emails/batch \
  -H "Authorization: Bearer $SENDR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <hello@acme.com>",
    "subject": "Your order update",
    "emails": [
      {"to": "alice@example.com", "html": "<p>Alice, your order shipped!</p>"},
      {"to": "bob@example.com", "html": "<p>Bob, your order shipped!</p>"}
    ]
  }'

Response

{
  "data": [
    {"id": "em_abc123", "status": "queued"},
    {"id": "em_abc124", "status": "queued"}
  ]
}

Get email

GET /v1/emails/:id

Requires read_only scope.

Response

{
  "id": "em_abc123",
  "from": "Acme <hello@acme.com>",
  "to": ["user@example.com"],
  "subject": "Welcome to Acme!",
  "status": "delivered",
  "created_at": "2025-03-12T09:00:00Z",
  "sent_at": "2025-03-12T09:00:01Z",
  "last_event": "opened",
  "region": "us-east-1",
  "attachments": []
}

Status values: queued, sent, delivered, bounced, complained


List emails

GET /v1/emails

Requires read_only scope.

Query parameters

ParameterTypeDefaultDescription
limitnumber50Results per page (1–100).
cursorstringPagination cursor from previous response's next_cursor.
statusstringFilter by status: queued, sent, delivered, bounced, complained.

Response

{
  "data": [
    {
      "id": "em_abc123",
      "from": "Acme <hello@acme.com>",
      "to": ["user@example.com"],
      "subject": "Welcome to Acme!",
      "status": "delivered",
      "created_at": "2025-03-12T09:00:00Z",
      "sent_at": "2025-03-12T09:00:01Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Pagination is cursor-based. Pass next_cursor as the cursor parameter to get the next page.


Cancel email

DELETE /v1/emails/:id

Requires full_access scope. Cancels a scheduled or queued email. Returns an error if the email has already been sent.

Response

{
  "id": "em_abc123",
  "status": "cancelled"
}

On this page