Transactional Send

Send one message that a person's own action asked for, such as a password reset, a receipt or a confirmation code. It goes to one to five recipients. For anything bulk, use a campaign.

POST /api/v1/send

Needs a bearer API key (see API Overview).

{
  "to": "ada@example.com",
  "subject": "Your receipt",
  "html": "<p>Thanks for your order.</p>",
  "text": "Thanks for your order.",
  "replyTo": "support@example.com"
}
FieldNotes
toRequired. One address or an array of up to 5. Duplicates are removed. Any invalid address rejects the request
subjectRequired. Control characters are stripped and the subject is cut at 500 characters
htmlThe HTML body. Send html, text, or both
textThe plain text body. If you send only text, it is wrapped in a minimal HTML page
replyToOptional address. Defaults to the workspace reply-to, if one is set

The message comes from your workspace's sending address: your verified custom domain if you have one, otherwise the shared Flomailr address, with your workspace's from name.

Response

{ "data": { "sent": 1, "failed": 0, "blocked": [] } }

blocked lists recipients that were skipped and why, as { "email": "...", "reason": "..." }. Reasons are SUPPRESSED_HARD_BOUNCE, SUPPRESSED_COMPLAINT, SUPPRESSED_MANUAL and BLOCKED_DOMAIN.

If every recipient is blocked the request returns 422. If every send attempt fails it returns 502.

How it differs from campaign mail

Transactional mail follows different rules on purpose:

  • No unsubscribe footer, no List-Unsubscribe header, and no postal address requirement.
  • No open or click tracking is added.
  • A marketing unsubscribe does not block it. Someone who left your newsletter can still get a password reset.
  • Quiet hours and the daily send cap do not apply.

These still apply:

  • Addresses suppressed for a hard bounce, a spam complaint or a manual block are skipped.
  • Domains in your blocked-domains list are skipped.
  • The workspace must not be suspended, and the guardrails master switch must be on (otherwise 403).
  • The message counts toward your monthly sending limit. A send that would pass it returns 402 with code QUOTA_EXCEEDED.

See Compliance for where the line between transactional and marketing mail sits.

Idempotency

Send an Idempotency-Key header to make retries safe:

curl -X POST https://flomailr.com/api/v1/send \
  -H "Authorization: Bearer $FLOMAILR_KEY" \
  -H "Idempotency-Key: receipt-1042" \
  -H "Content-Type: application/json" \
  -d '{"to":"ada@example.com","subject":"Your receipt","text":"Thanks for your order."}'
  • A repeat with the same key and the same request returns the original result without sending again, and the response includes "replayed": true.
  • The same key with a different request returns 409 with code CONFLICT.
  • The same key while the first request is still running returns 409.

Errors

HTTPCodeWhen
400VALIDATION_ERRORThe body is not valid JSON
422VALIDATION_ERRORMissing or invalid recipients, subject or body, or all blocked
402QUOTA_EXCEEDEDThe send would pass the monthly limit
403FORBIDDENThe workspace is suspended or guardrails are off
409CONFLICTIdempotency-Key reused with a different request, or still running
502INTERNAL_ERROREvery recipient failed to send