Skip to content
simailDocsv0

API reference

Send message

Send a new message, reply, reply-all or forward. Idempotent, checked against your send policy, and held for approval when a rule says so.

docs.simail.ai/api/send-message

POST/v0/inboxes/{inbox_id}/messages/send

Permission message_send. Idempotency-Key required. The message is submitted to the release service, which runs the checks below and answers with a send_id you can follow at GET /v0/sends/{send_id}. Guide: Drafts & sending.

curl -s https://api.simail.ai/v0/inboxes/shop-helper@simail.email/messages/send \
-H "Authorization: Bearer $SIMAIL_API_KEY" \
-H "Idempotency-Key: order-1042-shipped" \
-H "Content-Type: application/json" \
-d '{ "to": ["ada@example.com"], "subject": "Your order shipped", "text": "Hi Ada, your order #1042 shipped today.", "labels": ["orders"] }'

The release service runs these in order. The first one that fails decides the response.

#CheckFails with
1the body is valid and Idempotency-Key is present400
2the key is valid, claimed, in scope for this inbox and has message_send404 / 403
3the organization may send (not paused)403
4the same Idempotency-Key was not used with a different body409
5header fields have no CR, LF, NUL or control characters422
6the message is not too large (5 MiB including encoding, 32 attachments)413
7the thread is not locked by a human, and the inbox is not paused423
8deterministic checks and your send policy: sender, recipients, content, block lists, suppressions, loops422
9the same message was not already sent inside the de-duplication window409
10today’s limits would not be exceeded429
11sending is not paused platform-wide503
12approval rules (first contact, risk flags) decide whether the message waits for a human (pending_approval)202

Step 2 answers 404 not_found for an inbox outside your scope, and 403 missing_permission or 403 claim_required for a key that is not claimed or lacks message_send. Even after sent, delivery is reported later by message.delivered or message.bounced events.

NameTypeNotes
inbox_idstring, requiredthe sending inbox (its address)
NameTypeNotes
AuthorizationBearer <key>, requireda key with message_send for this inbox
Idempotency-Keystring, required, at most 255 charactersyour stable ID for this send; reuse it when you retry
NameTypeNotes
tostring[], requiredrecipients; to + cc + bcc at most 50 addresses
ccstring[]
bccstring[]only if your policy allows bcc
subjectstring
textstringplain-text body; send text, html or both (always send text)
htmlstringHTML body; no remote images or tracking are added
attachmentsobject[]{ "filename", "content_type", "content" } with base64 content, or { "draft_attachment_id" }; at most 32, about 3.5 MiB raw in total
labelsstring[]labels for the sent copy
send_atISO 8601send later, up to 30 days ahead; sent within about 2 minutes of that time
expected_recipientsstring[]if the recipients simail derives differ, the send is blocked (expected_recipients_mismatch)
headersobjectrejected, except X-Simail-Client-Ref
reply_tostringignored: simail sets Reply-To so replies thread correctly
track_opensbooleanignored: simail never tracks opens or clicks
{ "send_id": "out_01JZX4C0D1E2F3G4H5J6K7M8N9", "message_id": "msg_01JZX4C0D1E2F3G4H5J6K7M8NA", "thread_id": "thr_01JZX4C0D1E2F3G4H5J6K7M8NB", "status": "sent" }

status is sent (handed to the mail network), sending, or scheduled (with send_at).

{ "send_id": "out_01JZX4C0D1E2F3G4H5J6K7M8NC", "thread_id": "thr_01JZX4C0D1E2F3G4H5J6K7M8ND", "status": "pending_approval", "flags": ["first_contact", "has_links"] }

A human decides. Follow GET /v0/sends/{send_id} or the approval.decided event; do not resend. See Approvals & send policy.

The same message was already sent from this inbox inside the de-duplication window. Do not resend.

The Idempotency-Key was used before with a different body.

Carries limit_bytes and estimated_bytes. Remove or shrink attachments.

{
"type": "https://docs.simail.ai/errors#send_blocked",
"title": "SendBlockedError",
"status": 422,
"code": "send_blocked",
"message": "The message contains a template placeholder.",
"fix": "The pre-send check rejected this message; see `reasons`.",
"retryable": false,
"reasons": ["placeholder"],
"request_id": "req_01JZX4C0D1E2F3G4H5J6K7M8NF"
}

reasons lists every blocking check; see pre-send checks.

A human has taken over the thread. Stop and wait for thread.unlocked. See Human takeover.

Today’s limit is used up. Retry after Retry-After with the same Idempotency-Key.

Sending is paused platform-wide. Retry later with the same Idempotency-Key.

POST/v0/inboxes/{inbox_id}/messages/{message_id}/reply

Permission message_send, Idempotency-Key required. Body: text, html, attachments, labels, send_at, expected_recipients. The recipient is the original message’s From address (never its Reply-To); the subject gets Re: and threading headers are set for you. Replying to an auto-reply, a bounce or another simail agent is blocked (loop_auto_reply).

POST/v0/inboxes/{inbox_id}/messages/{message_id}/reply-all

Like reply, plus the original To and Cc, without your own address. Pass expected_recipients to make sure a reply never turns into a broadcast.

POST/v0/inboxes/{inbox_id}/messages/{message_id}/forward

Permission message_send, Idempotency-Key required. Body: to, cc, bcc, text (your note), labels. The subject gets Fwd:; original attachments are included, so a large message can exceed the 5 MiB limit (413 message_too_large; forward without attachments instead). Forwarding to new recipients counts as first contact for approval rules.

send_message, reply_to_message, reply_all_message and forward_message take the same fields plus a required idempotency_key. See MCP.