Skip to content
View as Markdown

Sending email ​

There are two ways to send a single email. Both take the same body.

POST /v1/sendPOST /v1/enqueue
Returnsafter your SMTP server accepts the emailas soon as the email is queued
Response includesmessageId and outboxIdoutboxId and queuedAt
On a temporary failureyou get the error and decideretried in the background
PlanFree and ProPro

Use /send when the caller needs to know the email went out — a password reset, a login code. Use /enqueue when it should not wait — a welcome email after sign-up, a notification from a request handler. For one message to many people, use a batch.

The request body ​

json
{
  "from": "you@yourcompany.com",
  "to": ["alice@example.com", "bob@example.com"],
  "cc": "manager@example.com",
  "bcc": "archive@yourcompany.com",
  "subject": "Weekly report",
  "text_body": "Numbers are up.",
  "html_body": "<h1>Weekly report</h1><p>Numbers are up.</p>"
}
FieldRequired
toyesRecipients. A single address, a comma-separated string, or an array.
subjectyesNon-empty.
text_bodyone of the twoPlain-text body.
html_bodyone of the twoHTML body. Send text_body too — some clients and spam filters prefer it.
fromnoAddress of one of your connections. Omit to use your default connection.
cc, bccnoSame formats as to.

/send accepts at most 10 recipients in total across to, cc and bcc; more returns 400 TOO_MANY_RECIPIENTS. To reach more people, send a batch — it also sends each recipient their own copy instead of exposing the whole list in to.

POST /v1/send ​

bash
curl https://api.marleyfetch.com/v1/send \
  -H "Authorization: Bearer $MARLEYFETCH_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: reset-password-8f3a2c" \
  -d '{
    "from": "security@yourcompany.com",
    "to": "user@example.com",
    "subject": "Reset your password",
    "text_body": "Use this link to reset your password: https://...",
    "html_body": "<p>Use <a href=\"https://...\">this link</a> to reset your password.</p>"
  }'
ts
await mf.from('security@yourcompany.com')
  .to('user@example.com')
  .subject('Reset your password')
  .text_body('Use this link to reset your password: https://...')
  .html_body('<p>Use <a href="https://...">this link</a> to reset your password.</p>')
  .send()

Response:

json
{
  "success": true,
  "messageId": "<send-4821@mid.marleyfetch.com>",
  "outboxId": 4821,
  "from": "security@yourcompany.com",
  "message": "Email sent successfully"
}

If your SMTP server rejects the message, you get a 500 whose message is the server's reason, for example 535 5.7.8 Username and Password not accepted. The failed attempt does not count against your quota.

Safe retries with Idempotency-Key ​

A request can time out after the email was sent. Retrying blindly would send it twice. Add an Idempotency-Key header — any string unique to this email, such as a UUID or order-1042-shipped — and reuse it on retries:

  • If the first request succeeded, the retry returns its result with "replayed": true. Nothing is sent again.
  • If the first request failed, the retry returns that failure with "success": false and "replayed": true. Use a new key to try again.
  • If the first request is still running, the retry gets 400 IDEMPOTENCY_KEY_IN_FLIGHT. Wait a moment and retry with the same key.

Keys are scoped to your account. Idempotency-Key is supported on /send.

POST /v1/enqueue ​

bash
curl https://api.marleyfetch.com/v1/enqueue \
  -H "Authorization: Bearer $MARLEYFETCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "new-user@example.com",
    "subject": "Welcome aboard",
    "html_body": "<p>Thanks for signing up.</p>"
  }'
ts
await mf.to('new-user@example.com')
  .subject('Welcome aboard')
  .html_body('<p>Thanks for signing up.</p>')
  .enqueue()

Response:

json
{
  "success": true,
  "message": "Email queued successfully",
  "outboxId": 4822,
  "from": "you@yourcompany.com",
  "queuedAt": "2026-09-28T10:15:00.000Z"
}

A background worker sends the email, usually within seconds, and retries it if your provider is briefly unavailable or rate-limiting. The API has no status endpoint for single emails yet; follow them in the Email Outbox by outboxId.

/enqueue is a Pro feature. On the Free plan it returns 403 FEATURE_NOT_AVAILABLE.

Limits ​

  • /send: at most 10 recipients per request, and the Free plan's 100 emails a day.
  • Both endpoints: the connection's own quota. /send answers 429 when it is used up; queued emails wait for the next window instead.

See Errors for every error code and how to handle it.