# Conversations

> Read customer conversations and their messages, reply, hand over to the team and back to the assistant, close, reopen and label them.

Source: https://www.ordstage.com/docs/conversations/

Conversations are the business's chats with customers on every channel (WhatsApp, Instagram, Messenger, website
chat, email and others). A key sees all of them, like an owner in the **Inbox**, and changes them with the Inbox's
rules.

| Scope | Lets a key |
|---|---|
| `conversations:read` | List conversations, read one and its messages, list labels. |
| `conversations:write` | Reply, hand over, return to the assistant, close, reopen, update and label. |

Internal notes between teammates are never part of the API.

## Reading

`GET /v1/conversations` lists conversations oldest first, filtered by `status`, `handled_by` (`assistant` or
`team`), `contact_id` or `channel_id`. `GET /v1/conversations/{conversation_id}/messages` lists what the customer
and the business said, each message with its `author`: `customer`, `assistant`, `team`, `campaign` or `system`.

## Replying

```bash [curl]
curl -X POST https://api.ordstage.com/v1/conversations/6f1c2e4a-8b3d-4c5e-9f70-1a2b3c4d5e6f/reply \
  -H "Authorization: Bearer $ORDSTAGE_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"content": "Your appointment is confirmed for Sunday at 10."}'
```

The reply is sent on the conversation's channel **as the key's creator**, who must still be an owner or admin (or
hold the conversations permission). Channel rules apply: for example WhatsApp only allows free-form replies within
24 hours of the customer's last message. A reply the channel can't take answers `409 reply_not_sent` with the
reason, and nothing is saved. The `Idempotency-Key` makes retries safe: the same key never sends twice.

With **test keys** replies go to the sandbox's sample website chat, are saved there and recorded as simulated
sends; nothing is ever sent.

## Who handles it, and its status

| Request | Effect | Event |
|---|---|---|
| `POST .../handover` | The team takes over; optionally to a member (`assigned_member_id`) or Inbox team (`team_id`). | `conversation.handed_over` |
| `POST .../return_to_assistant` | The assistant answers again. | `conversation.returned_to_assistant` |
| `POST .../close` | Marks it resolved (and tells the channel where it supports that). | `conversation.closed` |
| `POST .../reopen` | Opens it again. | `conversation.reopened` |
| `PATCH /v1/conversations/{id}` | Priority, assignee, team, or `pending` (waiting for the customer). | `conversation.updated` |

A member who can't take the conversation now (away, at capacity, not in the inbox) answers
`409 assignee_not_available`. Closing a closed conversation, or reopening an open one, changes nothing.

## Labels

`GET /v1/labels` lists the business's Inbox labels. Add one with `POST .../labels` (`{"label_id": "…"}`) and
remove it with `DELETE .../labels/{label_id}`; both send `conversation.updated` with `"changed": ["labels"]`.
Replies sent from the Inbox or the API send `conversation.reply_sent`.
