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

# Enviar mensagens

> Contrato PIV1 do Chat: from, to, type e payload. Texto, imagem, áudio e arquivo.

<Tip>
  O envio do Chat usa o **mesmo contrato** dos outros canais: `from`, `to`, `type` e `payload`. A diferença: `to` é o **id da conversa**, não um telefone.
</Tip>

## Endpoint

```http theme={null}
POST /v1/chat/messages
Content-Type: application/json
Authorization: Bearer sk_live_xxxxx
```

Escopo: **`chat:messages:send`**. Cada envio consome **1 crédito** (`CHAT_MESSAGE`).

O path `POST /v1/chat/conversations/{id}/messages` continua válido: o id da conversa vai na URL e o corpo é o mesmo (`type` + `payload`), sem `to`.

## Campos

| Campo                  | Obrigatório          | O que é                                                |
| ---------------------- | -------------------- | ------------------------------------------------------ |
| `from`                 | Não                  | Id do Chat App. Se vier, precisa ser o app da conversa |
| `to`                   | Sim neste endpoint   | Id da conversa: string ou array                        |
| `type`                 | Sim                  | `text`, `image`, `audio` ou `file`                     |
| `payload.message`      | Sim se `type=text`   | Texto. Em mídia, vira legenda (`caption` também vale)  |
| `payload.mediaUrl`     | Sim se não for texto | URL **HTTPS** da mídia                                 |
| `senderExternalUserId` | Sim com API Key      | Quem fala: `externalUserId` de um `USER` ou `AGENT`    |
| `clientMessageId`      | Não                  | Idempotência: o mesmo id devolve a mesma mensagem      |
| `replyToId`            | Não                  | Id da mensagem citada                                  |

Com **JWT do membro**, não envie `senderExternalUserId`: o remetente é o token.

A resposta usa `type` em maiúsculas (`TEXT`, `IMAGE`, `AUDIO`, `FILE`).

***

## Texto

```json theme={null}
{
  "from": "clxxapp...",
  "to": ["cnv_xxxxx"],
  "type": "text",
  "payload": {
    "message": "Oi, Alice. Seu pedido saiu para entrega."
  },
  "senderExternalUserId": "agent:clxxuser...",
  "clientMessageId": "msg_text_001"
}
```

**Resposta (200)**

```json theme={null}
{
  "success": true,
  "idempotent": false,
  "data": {
    "id": "clxxmsg...",
    "conversationId": "cnv_xxxxx",
    "type": "TEXT",
    "body": "Oi, Alice. Seu pedido saiu para entrega.",
    "mediaUrl": null,
    "createdAt": "2026-09-06T03:10:00.000Z"
  }
}
```

***

## Imagem

```json theme={null}
{
  "from": "clxxapp...",
  "to": ["cnv_xxxxx"],
  "type": "image",
  "payload": {
    "mediaUrl": "https://cdn.seusite.com/comprovante.png",
    "message": "Comprovante da entrega"
  },
  "senderExternalUserId": "user_alice"
}
```

`payload.message` (ou `payload.caption`) é a legenda. Sem `payload.mediaUrl` → **400**.

***

## Áudio

```json theme={null}
{
  "from": "clxxapp...",
  "to": ["cnv_xxxxx"],
  "type": "audio",
  "payload": {
    "mediaUrl": "https://cdn.seusite.com/recado.ogg"
  },
  "senderExternalUserId": "user_bob"
}
```

***

## Arquivo

```json theme={null}
{
  "from": "clxxapp...",
  "to": ["cnv_xxxxx"],
  "type": "file",
  "payload": {
    "mediaUrl": "https://cdn.seusite.com/contrato.pdf",
    "message": "Contrato assinado"
  },
  "senderExternalUserId": "agent:clxxuser..."
}
```

***

## Responder a uma mensagem

```json theme={null}
{
  "from": "clxxapp...",
  "to": ["cnv_xxxxx"],
  "type": "text",
  "payload": { "message": "Combinado, obrigado" },
  "senderExternalUserId": "agent:clxxuser...",
  "replyToId": "clxxmsg..."
}
```

`replyToId` também pode ir em `payload.replyToId`.

***

## JWT do membro

O app autenticado com o JWT **não** manda API Key.

```http theme={null}
POST /v1/chat/messages
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
```

```json theme={null}
{
  "to": ["cnv_xxxxx"],
  "type": "text",
  "payload": { "message": "Cheguei" }
}
```

***

## Várias conversas no mesmo pedido

`to` aceita lista. Cada id é uma conversa do mesmo workspace.

```json theme={null}
{
  "from": "clxxapp...",
  "to": ["cnv_aaaa", "cnv_bbbb"],
  "type": "text",
  "payload": { "message": "Manutenção às 22h" },
  "senderExternalUserId": "agent:clxxuser..."
}
```

Uma conversa → `data` é o objeto da mensagem. Várias → `data` é um array.

***

## WebSocket (app do usuário)

O socket **não** usa o body PIV1. Depois do `auth`:

```json theme={null}
{ "type": "message.send", "conversationId": "cnv_xxxxx", "body": "Oi", "clientMessageId": "msg_ws_1" }
```

Mídia no socket: `messageType` (`image` | `audio` | `file`) e `mediaUrl` HTTPS, ou `payload.type` / `payload.mediaUrl`. O `type` do frame continua sendo `message.send`.

REST (backend) → `POST /v1/chat/messages`. Tempo real no app → WebSocket.

Tipo fora do teto do app ou do interruptor da sala → **403** `CHAT_CAPABILITY_DISABLED`. DIRECT com bloqueio entre os usuários → **403** `CHAT_USER_BLOCKED`. Detalhes: [Capacidades e bloqueio](/chat-api/como-funciona/capacidades-e-bloqueio).

No WebSocket o `message.send` também aceita `type` (`text` | `image` | `audio` | `file`) e `mediaUrl` (HTTPS). `recording.start` só vale se a sala tiver `audio` ligado.

## Próximos passos

* [Usuário e agente](/chat-api/como-funciona/usuario-e-agente): quem aparece como remetente
* [Eventos dos webhooks](/chat-api/como-funciona/eventos-do-webhooks)
* [Escopos da API Key](/chat-api/como-funciona/escopos-da-api-key)
