> ## Documentation Index
> Fetch the complete documentation index at: https://docs.osis.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Send your first message

> Request body, channels, idempotency, and what a 202 means on the wire.

This guide walks through a production-shaped outbound send: auth, body fields, idempotency, and how to interpret the response.

## Prerequisites

* A workspace with a live line.
* A Messages API key with `comms_send`.
* A phone number you control for testing (`to` in E.164).

## Request

```http theme={null}
POST /api/v1/comms/messages
Host: osis.co
Authorization: Bearer osis_…
Content-Type: application/json
Idempotency-Key: order-4242-confirm
```

```json theme={null}
{
  "to": "+12125550147",
  "body": "Your appointment is confirmed for Tuesday at 3pm.",
  "channel": "imessage"
}
```

### Fields

| Field             | Required                        | Notes                                               |
| ----------------- | ------------------------------- | --------------------------------------------------- |
| `to`              | One of `to` / `conversation_id` | E.164, e.g. `+12125550147`                          |
| `conversation_id` | One of `to` / `conversation_id` | Continue an existing thread                         |
| `body`            | Yes                             | Plain text for SMS / iMessage                       |
| `channel`         | No                              | `"sms"` or `"imessage"` when you want to prefer one |
| `idempotency_key` | No                              | Same as header; either works                        |

### Auth

```http theme={null}
Authorization: Bearer $COMMS_API_KEY
```

Missing or invalid key → **401**. Missing `comms_send` → **403** with `{ "error": "missing comms_send scope" }`.

## Response

### Accepted

**202** — Comms accepted the message for delivery.

```json theme={null}
{
  "message": {
    "id": "msg_…",
    "body": "Your appointment is confirmed for Tuesday at 3pm.",
    "direction": "outbound"
  }
}
```

### Duplicate

**200** — Same idempotency key already processed. No second send.

```json theme={null}
{
  "message": { "id": "msg_…", "body": "…", "direction": "outbound" },
  "duplicate": true
}
```

Treat **202** and duplicate **200** as success for your queue / job runner.

## Idempotency

Use a stable key derived from your business event:

```text theme={null}
order-{orderId}-shipped
booking-{bookingId}-reminder-1
```

If your worker crashes after the POST but before recording success, the retry hits the same key and Comms returns the original result. Full detail: [Idempotency](/guides/idempotency).

## Channels

| Value        | Behavior                                     |
| ------------ | -------------------------------------------- |
| omitted      | Comms picks the best path for that recipient |
| `"imessage"` | Prefer iMessage when available               |
| `"sms"`      | Force SMS                                    |

Not every recipient can receive iMessage. Prefer omitting `channel` unless you have a product reason.

## Continuing a thread

First touch:

```json theme={null}
{ "to": "+12125550147", "body": "Hi — this is Alex from Acme." }
```

Later replies in the same conversation (using an id you stored):

```json theme={null}
{
  "conversation_id": "conv_…",
  "body": "Your table is ready."
}
```

## Checklist for production

<AccordionGroup>
  <Accordion title="Key lives only on the server">
    Inject `COMMS_API_KEY` from your secret store. Never embed it in a frontend bundle.
  </Accordion>

  <Accordion title="Every send has an Idempotency-Key">
    Derive it from the domain event so retries are safe.
  </Accordion>

  <Accordion title="Log status + message id">
    Persist `message.id` and HTTP status so support can trace a send without reading phone logs.
  </Accordion>

  <Accordion title="Handle 429">
    Back off using `retry_after` when present. See [Errors & rate limits](/guides/errors-and-rate-limits).
  </Accordion>
</AccordionGroup>

## Related

* [Send message reference](/messages-api/send-message)
* [List messages](/messages-api/list-messages)
* [Webhooks](/guides/webhooks)
