Guide

Send an email in one HTTP request

One endpoint, one JSON body, one response. Working samples in cURL, Python, Node.js, PHP and Go, then the fields that matter and the ones you can leave out.

The request

HTTP
POST https://sendfleet.net/api/send/
X-API-Key: sk_live_your_key
Content-Type: application/json

There is no SDK and no client library. If your language can make an HTTP request with a JSON body, it can send email.

The smallest body that works

One recipient per request. At least one of message, html or attachments is required, plus a sender and a recipient.

JSON body
{
  "to": "user@example.com",
  "from_email": "hello@yourdomain.com",
  "from_name": "Acme",
  "subject": "Your order is confirmed",
  "message": "Thanks for your order!"
}

The same request in five languages

cURL
curl -X POST https://sendfleet.net/api/send/ \
  -H "X-API-Key: sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "user@example.com",
    "from_email": "hello@yourdomain.com",
    "from_name": "Acme",
    "subject": "Your order is confirmed",
    "message": "Thanks for your order!"
  }'

The response

200 OK
{
  "success": true,
  "mode": "byoc",
  "idempotency_key": "8f14e45fceea167a5a36dedd4bea2543"
}

mode tells you which sending path handled the message: byocmeans it went out through the customer's own AWS account, sharedthrough SendFleet's. It reflects the sending domain, not the plan name.

This is an acknowledgement, not a delivery confirmation. The response means the message was accepted for delivery. What happened next arrives later, and only if you have set up a webhook endpoint.

Fields

Request fields
FieldRequiredWhat it does
toYesOne recipient address.
from_emailYesThe sending address. Must be on a verified domain.
from_nameNoDisplay name shown next to the address.
subjectNoSubject line.
messageOne of threePlain-text body.
htmlOne of threeHTML body. Takes precedence over message when both are sent.
reply_toNoWhere replies go, if not from_email.
attachmentsOne of threeBase64-encoded files. SendRawEmail carries them.
idempotency_keyNoYour own key for this send. Use it to make a retry safe.

When it fails

Errors come back as a JSON object with a single error key holding a machine-readable code, alongside an HTTP status that tells you the class of problem.

Error response
{
  "error": "domain_not_verified"
}
The statuses you will see most
StatusMeaningWhat to do
400The request body is invalid.Fix the body. Do not retry unchanged.
401The API key is missing, malformed or revoked.Check the key. Do not retry.
403The key cannot send to this domain, or sending is suspended.Check domain scoping and account status.
429Rate limited, or over the plan's monthly limit.Back off. Distinguish the two from the error code.
503The BYOC role could not be used.Check the role still exists and still validates.

The Error Codes reference has every code, what causes it, and whether retrying is safe.

Rate limit

60 requests per minute per key, on every plan. Exceeding it returns HTTP 429. If you need more than that, the ceiling is per key, so several keys will carry several ceilings.

HTML and plain text together

Send both when you can. html is what most recipients see, and message is what a text-only client reads.

Both bodies
{
  "to": "user@example.com",
  "from_email": "hello@yourdomain.com",
  "subject": "Your order is confirmed",
  "message": "Thanks for your order!",
  "html": "<p>Thanks for your order!</p>"
}

Next

Send Email has every field in full, including attachments. Verify webhook signatures covers what to do with the delivery events this request produces.