Sendr365 Developer Documentation

Welcome

Sendr365 Developer Docs

Sendr365 is a multi-channel email infrastructure platform — transactional API, SMTP relay, marketing campaigns, contact management, and webhook events. This guide walks you from a first API call to production sending.

Every endpoint accepts JSON over HTTPS. Authentication is via a tenant API key (X-API-Key header) — generated in your dashboard. All paths are versioned under https://sendr365.com/api/v1.

5-minute goal: read Quick start, copy your API key, and send your first email. Code is in Node.js / Python / cURL — pick whatever your stack is.

What's in here

Quick start

Send your first email in 5 minutes

Three steps: sign up, generate an API key, send a test email. No credit card required — every new account gets 100 free emails for 30 days — 50 transactional + 50 marketing.

1

Create an account

Sign up at sendr365.com/signup — verify your email, you're in. Your account starts with 100 credits each in transactional and marketing pools.

2

Generate an API key

Open Settings → API keys, click Generate, and copy the key. It's shown once; store it in your secrets manager.

3

Send a test email

Use your key in the X-API-Key header. The example below sends a plain HTML email to one recipient.

curl -X POST 'https://sendr365.com/api/v1/email/send' \
  -H 'X-API-Key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "to": "[email protected]",
    "subject": "Hello from Sendr365",
    "html": "<h1>It works!</h1><p>This is your first email.</p>"
  }'

Response

json
{
  "sent": 1,
  "skipped": 0,
  "failed": 0,
  "results": [
    { "to": "[email protected]", "messageId": "msg_2K9xQz3vN8mLp4yF", "status": "sent" }
  ],
  "creditsRemaining": 99
}
That's it. The recipient sees the email within a few seconds. Track delivery, opens, and clicks in the Metrics dashboard.

Auth

Authentication

Tenant endpoints are authenticated with an API key in the X-API-Keyheader. Each key is scoped to one account — keep keys server-side, never embed in browser code.

API key scopes

Every key has a set of scopes. Pick the minimum scope your integration needs — narrower scopes reduce blast radius if a key leaks.

ScopeWhat it allows
transactional:sendSend via /email/send (debits TXN credits)
campaigns:readRead campaign metadata + reports
campaigns:writeCreate/schedule/cancel campaigns
contacts:readRead contacts + lists
contacts:writeCreate/update/delete contacts + lists
events:readRead send/open/click events for analytics

Header format

http
X-API-Key: sk_live_AbCdEf123456...
Never expose API keys in browser code or git repos. Use environment variables + a secret manager. If a key leaks, revoke it immediately at/app/settings/api-keys.

Rate limits

Default rate limit: 10 requests/sec per key, with burst tolerance. Hit a limit → 429 Too Many Requests with a Retry-Afterheader. Upgrade plans raise the ceiling.

Transactional

Send a single email

The POST /email/send endpoint sends one transactional email synchronously. Use it for OTP codes, password resets, receipts, alerts — anything triggered by a single user action.

When to use this

  • One-off, system-generated emails to a single recipient
  • Time-sensitive sends (login codes, order confirmations)
  • Emails triggered programmatically from your backend

Request body

FieldTypeRequiredDescription
tostringyesRecipient email address
subjectstringyesEmail subject (max 300 chars)
htmlstringyesHTML body (sanitized server-side)
textstringnoPlaintext fallback
fromEmailstringnoOverride the default sender. Must be on a verified domain.
fromNamestringnoOverride the sender display name
replyTostringnoReply-To address
variablesobjectnoPersonalization values (e.g. {"name":"Alice"}) — referenced as {{name}} in body
headersobjectnoCustom headers (e.g. X-Campaign-Id)

Code examples

curl -X POST 'https://sendr365.com/api/v1/email/send' \
  -H 'X-API-Key: $SENDR365_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "to": "[email protected]",
    "subject": "Your order #1234 is confirmed",
    "html": "<h1>Thanks Alice!</h1><p>Your order ships tomorrow.</p>",
    "fromEmail": "[email protected]",
    "fromName": "Acme Store"
  }'

Response

json
{
  "sent": 1,
  "skipped": 0,
  "failed": 0,
  "results": [
    { "to": "[email protected]", "messageId": "msg_2K9xQz3vN8mLp4yF", "status": "sent" }
  ],
  "creditsRemaining": 99
}

Batch sending

To send many transactional emails in one request, post { "messages": [...] } with up to 500 message objects, each with the same fields shown above. Credits are debited atomically for the whole batch up-front.

Marketing

Send a campaign to a list

Campaigns send the same email to many recipients with throttling, suppression filtering, and per-recipient tracking. Use these for newsletters, broadcasts, and re-engagement flows.

Lifecycle

  • Create a draft (subject, sender, body)
  • Schedule it against one or more lists
  • Worker expands the audience and dispatches at your configured rate
  • Each recipient deducts 1 marketing credit

Create + schedule

# 1. Create draft
curl -X POST 'https://sendr365.com/api/v1/campaigns' \
  -H 'X-API-Key: $SENDR365_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "April newsletter",
    "subject": "What we shipped this month",
    "fromEmail": "[email protected]",
    "fromName": "Acme Team",
    "bodyHtml": "<h1>Hello!</h1><p>...</p>"
  }'

# 2. Schedule it (returns campaignId)
curl -X POST 'https://sendr365.com/api/v1/campaigns/CAMPAIGN_ID/schedule' \
  -H 'X-API-Key: $SENDR365_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{ "listIds": ["list_abc"], "scheduledFor": "2026-05-01T10:00:00Z" }'
Marketing credits cost 3× transactional credits. Bulk sends require a verified sending domain.

Audience

Manage contacts and lists

Contacts are people you can send to. Lists are groups of contacts. Suppressions are global — a contact who unsubscribes won't receive any future marketing send from your account.

Add contacts to a list

curl -X POST 'https://sendr365.com/api/v1/contacts' \
  -H 'X-API-Key: $SENDR365_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "email": "[email protected]",
    "firstName": "Alice",
    "lastName": "Smith",
    "tags": ["vip"],
    "listIds": ["list_abc"]
  }'

Setup

Verify a sending domain

Add a domain you own, publish 3 DNS records (SPF, DKIM, DMARC), and Sendr365 auto-verifies within ~5 minutes. The default [email protected] identity is provisioned the moment verification completes.

Add domain

curl -X POST 'https://sendr365.com/api/v1/sending-domains' \
  -H 'X-API-Key: $SENDR365_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{ "domain": "yourdomain.com", "selector": "mf1" }'

Response

json
{
  "id": "dom_2KP4...",
  "domain": "yourdomain.com",
  "spfStatus": "PENDING",
  "dkimStatus": "PENDING",
  "dmarcStatus": "PENDING",
  "dnsRecords": {
    "spf":   { "host": "yourdomain.com",     "type": "TXT", "value": "v=spf1 include:..." },
    "dkim":  { "host": "mf1._domainkey...",  "type": "TXT", "value": "..." },
    "dmarc": { "host": "_dmarc.yourdomain.com", "type": "TXT", "value": "v=DMARC1; p=none; ..." }
  }
}

Publish the records at your registrar, then poll GET /sending-domains/:id— or just wait, the platform auto-checks every 3 minutes. Status flips through PENDING → CHECKING_DNS → VERIFYING_PROVIDER → ACTIVE.

Integrations

Connect via SMTP

Already using a tool that speaks SMTP? Point it at our relay and you're done — no API integration needed. Works with WordPress, Shopify, n8n, Zapier, and any custom backend.

SettingValue
Hostsmtp.sendr365.com
Port587 (STARTTLS), 465 (Implicit TLS), or 2525 (alt-submission)
UsernameGenerated in /app/settings/smtp
PasswordGenerated alongside username, shown once
Auth methodPLAIN or LOGIN
EncryptionSTARTTLS required (server rejects AUTH on plaintext)
Max message25 MB

Generate credentials

Open SMTP settings in your dashboard, click Generate credentials, and copy both the username + password. Each credential is independent — you can have one per integration.

Node.js (Nodemailer)

javascript
import nodemailer from 'nodemailer';

const transporter = nodemailer.createTransport({
  host: 'smtp.sendr365.com',
  port: 587,
  secure: false,        // STARTTLS upgrades the connection
  requireTLS: true,
  auth: {
    user: process.env.SENDR_SMTP_USER,
    pass: process.env.SENDR_SMTP_PASS,
  },
});

await transporter.sendMail({
  from: '"Acme" <[email protected]>',
  to: '[email protected]',
  subject: 'Order confirmed',
  html: '<p>Thanks!</p>',
});

Events

Webhooks

Outbound webhooks are on the roadmap — Sendr365 will POST real-time events (opens, clicks, bounces, complaints, unsubscribes) to a URL you control. Until that's live, use the polling endpoints below or the dashboard Metrics page.

Status: in development. The event types are tracked internally, but the outbound delivery service hasn't shipped yet. Don't build a system that depends on push webhooks today — use the events polling endpoint.

Today: see events in the dashboard

Events are tracked internally and surfaced in the Metrics dashboard with per-campaign breakdowns. A read API + push webhooks are next on the roadmap.

Event types tracked

TypeFires when
SENTEmail accepted by upstream MTA
DELIVEREDRecipient mailbox confirmed delivery
OPENRecipient opened (tracking pixel loaded)
CLICKRecipient clicked a tracked link
BOUNCEMailbox rejected the email
COMPLAINTRecipient marked as spam
UNSUBSCRIBERecipient hit the one-click unsubscribe link
DEFERREDTemporary delivery delay (recipient mailbox queue full, etc.)

What's coming

  • POST your endpoint a JSON payload per event with HMAC-SHA-256 signature
  • Configurable retry policy (exponential backoff, 24-hour give-up)
  • Dashboard UI to register endpoints and inspect delivery history
  • Per-event-type filtering so you only get the events you care about

Want webhooks now? Open a ticket at /app/support — we prioritize based on user demand.

Reference

Errors & rate limits

Errors return JSON with a stable error code your client can branch on. Always check status codes — 2xx = success, 4xx = your fault, 5xx = ours.

Error response format

json
{
  "statusCode": 400,
  "error": "INSUFFICIENT_CREDITS",
  "message": "Need 50 marketing credits; have 12 free + 0 paid",
  "have": { "free": 12, "paid": 0 },
  "category": "PROMO"
}

Common error codes

Codes in bold are stable — your client can safely branch on them. Others come from the framework's default HTTP error mapping.

HTTPCodeMeaning
400INSUFFICIENT_CREDITSAccount ran out of credits in the relevant pool
400DOMAIN_REQUIREDBulk send blocked — verified domain not yet set up
400SENDING_BLOCKEDFree trial expired or account suspended/canceled
401UnauthorizedMissing or invalid X-API-Key header
403ForbiddenAPI key lacks the required scope
404Not FoundResource doesn't exist on this account
409DOMAIN_LIMIT_REACHEDSingle-domain rule — delete current domain to add another
422VALIDATION_ERRORRequest body failed schema validation
429Too Many RequestsRate limit hit — see x-ratelimit-* response headers + Retry-After
503Service UnavailableUpstream provider temporarily unavailable

Rate limit windows

WindowLimitHeader
1 second10 requestsx-ratelimit-limit-short
1 minute60 requestsx-ratelimit-limit-medium
1 hour500 requestsx-ratelimit-limit-long
Every API response includes an X-Request-Id header. Include this in any support ticket — it lets us pull the full server-side log instantly.