Docs/Send Email
API Reference

Send Email

The single endpoint that powers all email delivery. Works identically for both BYOC and Shared SES - the routing decision is made automatically based on your sender domain.

POST/api/send/

Request headers

HeaderValueRequired
X-API-KeyYour API keyYes
Content-Typeapplication/jsonYes

Request body

All parameters are passed as a JSON object in the request body.

to
string · email
Required
Recipient email address. Must be a valid email format. If the recipient address appears on the suppression list (from a previous hard bounce or complaint), the request will be rejected with 422 recipient_suppressed.
from_email
string · email
Optional
Sender email address. The domain must match a verified, send-ready domain in your account. Effectively required - if omitted it falls back to your account's login email, which is almost certainly not a verified sending domain and will result in a domain_not_registered error.

This field drives routing. The sending_modeof the domain - set permanently when you added it to your account - determines the infrastructure path: domains added as BYOC route through your own AWS SES via your assumed IAM role; domains added as Shared SES route through SendFleet's managed infrastructure. Both use the same endpoint and the same API key.
from_name
string
Optional
Display name shown as the sender. Appears as from_name <from_email>in the recipient's inbox. Max 156 characters. If omitted, only the email address is shown.
subject
string
Optional
Email subject line. Max 256 characters. Defaults to (no subject) if omitted. Most spam filters flag emails without a subject - always provide one in production.
message
string
Required
Plain-text body of the email. Always required even when htmlis provided - used as fallback for clients that don't render HTML, and as the base content for spam filter analysis.
html
string · HTML
Optional
HTML body of the email. When provided, recipients with HTML-capable mail clients see this instead of message. Plain-text clients fall back to message. Use inline CSS only - most email clients strip <style> blocks.
reply_to
string · email
Optional
Email address replies should be directed to. Defaults to from_email when omitted. Useful for sending from a no-reply address while still receiving replies at a monitored inbox.

Request examples

curl -X POST https://sendfleet.net/api/send/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to":         "alice@example.com",
    "from_email": "hello@yourdomain.com",
    "from_name":  "Your App",
    "subject":    "Your order has shipped",
    "message":    "Hi Alice,\n\nYour order #1234 has shipped!\n\nTrack it here: https://track.example.com/1234\n\nThanks,\nYour App",
    "html":       "<p>Hi Alice,</p><p>Your order <strong>#1234</strong> has shipped!</p><p><a href=\"https://track.example.com/1234\">Track your order →</a></p>",
    "reply_to":   "support@yourdomain.com"
  }'

Successful response

HTTP 200 OK. The email has been accepted and queued - delivery is asynchronous.

200 OK - BYOC send
{
  "success":    true,
  "message":    "Email queued for delivery via your SES account.",
  "message_id": "1a2b3c4d-5e6f-7890-abcd-ef1234567890",
  "mode":       "byoc"
}
200 OK - Shared SES send (with deliverability warnings)
{
  "success":    true,
  "message":    "Email queued for delivery.",
  "message_id": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
  "mode":       "shared",
  "warnings": [
    "SPF record not verified. Add 'v=spf1 include:amazonses.com ~all' as a TXT record on yourdomain.com.",
    "DMARC record not found. Add 'v=DMARC1; p=none;' as a TXT record on _dmarc.yourdomain.com."
  ]
}

Response fields

FieldTypeDescription
successbooleanAlways true on HTTP 200.
messagestringHuman-readable confirmation string.
message_idstringUnique identifier for this queued send. For Shared SES, use this to correlate with your email logs. For BYOC, this is the SQS enqueue ID - delivery tracking is via your own AWS SES/CloudWatch.
modestring"byoc" or "shared" - which infrastructure path was used.
warningsstring[]Optional. Non-blocking deliverability issues (missing SPF, DMARC, MAIL FROM records). Shared SES only.
Warnings do not block delivery. Emails are still sent when warnings are present. However, missing DNS records significantly impact inbox placement. Address them from Dashboard → Domains.

Error responses

All error responses share the same shape. The error field is a machine-readable code; detail is a human-readable explanation.

Error response shape
{
  "success": false,
  "error":   "domain_not_verified",
  "detail":  "Domain 'yourdomain.com' is not yet verified by SES. Add the TXT ownership record and click Verify in the dashboard."
}
HTTPerrorCause
400(field errors)Missing or invalid request body fields.
401-Missing, invalid, or revoked API key.
403unauthorizedAccount not approved or email unverified.
403domain_not_registeredfrom_email domain not in your account.
403domain_not_verifiedDomain ownership not confirmed by SES.
403dkim_not_verifiedDKIM CNAME records not confirmed by SES.
403domain_mode_mismatchDomain's mode doesn't match your current plan.
403sending_suspendedAccount suspended due to bounce/complaint threshold.
422recipient_suppressedRecipient is on the suppression list.
429usage_limit_exceededMonthly email quota exhausted.
429-Rate limit hit (60 req/min).
502queue_errorSQS temporarily unavailable - retry with backoff.
503byoc_not_configuredBYOC infrastructure misconfiguration. Contact support.

See the full Error Codes reference → for retry guidance and handling strategies.

HTML email tips

Email HTML is not like browser HTML. Clients like Gmail, Outlook, and Apple Mail strip modern CSS and block external resources. Follow these rules:

RuleWhy
Use inline CSS only<style> blocks are stripped by Gmail and many mobile clients.
Use table-based layoutsCSS Flexbox/Grid are ignored by Outlook (which uses Word's rendering engine).
No external images (CDN-free)Many clients block external images by default. Embed or use hosted images with absolute URLs.
Always include plain-textRequired for spam filter scoring and accessibility.
Keep under 100 KBGmail clips emails over 102 KB, hiding the unsubscribe footer.
Test with Litmus or Email on AcidClient rendering varies wildly - test before large sends.