# Send message

Source: https://docs.simail.ai/api/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.

`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}`](/api/sends/). Guide: [Drafts & sending](/sending/).

```sh
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"] }'
```

## Checks before anything is sent

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

| # | Check | Fails with |
|---|---|---|
| 1 | the body is valid and `Idempotency-Key` is present | 400 |
| 2 | the key is valid, claimed, in scope for this inbox and has `message_send` | 404 / 403 |
| 3 | the organization may send (not paused) | 403 |
| 4 | the same `Idempotency-Key` was not used with a different body | 409 |
| 5 | header fields have no CR, LF, NUL or control characters | 422 |
| 6 | the message is not too large (5 MiB including encoding, 32 attachments) | 413 |
| 7 | the thread is not locked by a human, and the inbox is not paused | 423 |
| 8 | deterministic checks and your send policy: sender, recipients, content, block lists, suppressions, loops | 422 |
| 9 | the same message was not already sent inside the de-duplication window | 409 |
| 10 | today's limits would not be exceeded | 429 |
| 11 | sending is not paused platform-wide | 503 |
| 12 | approval 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.

## Parameters

### Path

| Name | Type | Notes |
|---|---|---|
| `inbox_id` | string, required | the sending inbox (its address) |

### Headers

| Name | Type | Notes |
|---|---|---|
| `Authorization` | `Bearer <key>`, required | a key with `message_send` for this inbox |
| `Idempotency-Key` | string, required, at most 255 characters | your stable ID for this send; reuse it when you retry |

### Body

| Name | Type | Notes |
|---|---|---|
| `to` | string[], required | recipients; `to` + `cc` + `bcc` at most 50 addresses |
| `cc` | string[] | |
| `bcc` | string[] | only if your policy allows `bcc` |
| `subject` | string | |
| `text` | string | plain-text body; send `text`, `html` or both (always send `text`) |
| `html` | string | HTML body; no remote images or tracking are added |
| `attachments` | object[] | `{ "filename", "content_type", "content" }` with base64 `content`, or `{ "draft_attachment_id" }`; at most 32, about 3.5 MiB raw in total |
| `labels` | string[] | labels for the sent copy |
| `send_at` | ISO 8601 | send later, up to 30 days ahead; sent within about 2 minutes of that time |
| `expected_recipients` | string[] | if the recipients simail derives differ, the send is blocked (`expected_recipients_mismatch`) |
| `headers` | object | rejected, except `X-Simail-Client-Ref` |
| `reply_to` | string | ignored: simail sets Reply-To so replies thread correctly |
| `track_opens` | boolean | ignored: simail never tracks opens or clicks |

## Responses

### 202 sent

```json
{ "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`).

### 202 pending_approval

```json
{ "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](/approvals/).

### 409 duplicate_send

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

### 409 idempotency_conflict

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

### 413 message_too_large

Carries `limit_bytes` and `estimated_bytes`. Remove or shrink attachments.

### 422 send_blocked

```json
{
  "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](/sending/#pre-send-checks).

### 423 thread_locked

A human has taken over the thread. Stop and wait for `thread.unlocked`. See [Human takeover](/takeover/).

### 429 daily_limit_exceeded

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

### 503 sending_paused

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

## Reply

`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`).

## Reply all

`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.

## Forward

`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.

## In MCP

`send_message`, `reply_to_message`, `reply_all_message` and `forward_message` take the same fields
plus a required `idempotency_key`. See [MCP](/mcp/).
