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

# Chats

> Conversas, mensagens, atendimento, responsáveis e agendamentos pela API externa.

As rotas de chat começam com `/integrations/external/chats`. Envie a [chave de integração](/documentacao-da-api/integracoes/autenticacao) no header `Authorization: Bearer <chave>`. A empresa é definida pela chave; as operações usam o usuário que criou a chave como ator e respeitam suas permissões e acesso aos números e contas.

## Canais e consulta de conversas

`GET /integrations/external/chats` reúne conversas WhatsApp e Instagram. Use `channel_type=WHATSAPP` ou `channel_type=INSTAGRAM` para restringir o canal. `phone_id` identifica um número WhatsApp; `channel_account_id`, sem `channel_type`, direciona a consulta para Instagram.

```bash theme={null}
curl --get 'https://api.wegly.com.br/integrations/external/chats' \
  --header "Authorization: Bearer $WEGLY_INTEGRATION_TOKEN" \
  --data-urlencode 'channel_type=WHATSAPP' \
  --data-urlencode 'status=OPEN' \
  --data-urlencode 'take=20'
```

A listagem retorna `total`, `records` e `next_cursor`. Envie o valor de `next_cursor` no parâmetro `cursor` para continuar com os mesmos filtros; `null` indica o fim. A ordenação pode mudar quando chegam mensagens, por isso prefira cursor para percorrer a listagem combinada. `skip` continua disponível. O padrão é `take=10`, com limite efetivo de 50 registros por página.

| Filtro | Comportamento |
| - | - |
| `search` | No WhatsApp, procura no nome do perfil do contato e no nome da pessoa vinculada; termos com formato de telefone também procuram no número do contato, com ou sem o nono dígito. |
| `status` | `OPEN`, `RESOLVED` ou `SNOOZED`. |
| `archived` | Sem filtro, exclui arquivados; `include` inclui; `only` retorna apenas arquivados. |
| `priority` | `0` baixa, `1` normal, `2` alta ou `3` urgente. |
| `person_id` | Pessoa do CRM vinculada à conversa. |
| `responsible_user_id` | Responsável do WhatsApp; atualmente exclui conversas Instagram. Um usuário que não é atendente do WhatsApp retorna lista vazia. |
| `unread_only=true` | Considera mensagens não lidas ou marcação manual de não lido. |
| `has_scheduled_messages=true` | Conversas WhatsApp com agendamentos pendentes ou em processamento, independentemente da data. |
| `has_pending_copilot_actions=true` | Conversas WhatsApp com ações pendentes de revisão do Copilot. |
| `customer_reply_status` | WhatsApp: `initial_replied`, `initial_not_replied` ou `not_replied_last_messages`. |
| `customer_reply_message_count` | Para `not_replied_last_messages`, quantidade de mensagens sem resposta, de 1 a 50; padrão 1. |

Os filtros positivos de agendamento, Copilot e resposta do cliente excluem Instagram. Os registros contêm `channel_type`, `channel_account_id`, `channel_account`, `external_contact` e `legacy`. No Instagram, `wa_contact_id` é `null` e `legacy` é vazio.

Nos registros de WhatsApp da listagem, `ai_attendance` resume o atendimento por agente de IA: `state` (`AI`, `TRANSFERRED` ou `TEAM`), `agent`, `since`, `end_reason` e `transferred_to`. O campo é `null` quando a conversa nunca teve agente de IA ou o recurso está desativado, e não faz parte dos detalhes nem dos registros de Instagram.

Use `GET /{id}` para detalhes, `GET /{id}/messages` para mensagens e `GET /{id}/history` para eventos operacionais. As listagens de mensagens usam `search`, `skip`, `take` e `order=asc|desc`, com padrão de 20 registros e limite efetivo de 100. `total` representa todos os registros encontrados. Uma mensagem citada pode incluir `quoted_message.page`.

Em mensagens WhatsApp, `media` é um objeto ou `null`; em mensagens Instagram, `media` e `attachments` são arrays. `content_payload` guarda o conteúdo estruturado e pode ser `null`. Instagram também expõe `provider_message_id`, `shared_content` e metadados do provedor; nesse canal, `status` vem em maiúsculas (`PROCESSING`, `SENT`, `DELIVERED`, `READ`, `FAILED` ou `DELETED`) e `error_code` é um texto. WhatsApp inclui `transcription`, `error_code`, `error_message` e dados de ligação quando disponíveis. `whatsapp_ai_agent_id` identifica o agente de IA que enviou a mensagem e é `null` nas mensagens de pessoas e automações. URLs de mídia e avatares podem ser temporárias.

A timeline `GET /{id}/timeline` é de WhatsApp e combina eventos `MESSAGE` e `CALL` em uma paginação única. Ao usar `search`, retorna somente mensagens cujo corpo corresponde à busca.

## Criar conversa e enviar mensagens

A criação manual é de WhatsApp. `POST /integrations/external/chats` exige `whatsapp_phone_id`, `template` e pelo menos um identificador de contato: `wa_contact_id` ou `person_contact_id`. O segundo é o UUID de um contato telefônico de uma pessoa do CRM. O serviço pode reutilizar uma conversa existente e envia o template inicial.

```json theme={null}
{
  "whatsapp_phone_id": "4d0c075c-bfa6-4466-8955-c7d8350a6420",
  "wa_contact_id": "5511999999999",
  "remote_profile_name": "Maria",
  "template": {
    "name": "saudacao_inicial",
    "language": "pt_BR"
  },
  "template_fields": [
    {
      "component": "BODY",
      "type": "TEXT",
      "index": 1,
      "value": "Maria"
    }
  ]
}
```

`crm_person_id`, `assigned_agent_id` e `status` também são opcionais. `assigned_agent_id` é o UUID do agente; as rotas de responsável e participante recebem `user_id`. Essa rota não recebe arquivos: se o template tiver mídia no cabeçalho, informe uma URL `http(s)` no `value` do campo.

Consulte `GET /{id}/templates` para obter templates da conta WhatsApp e os respectivos `required_fields`. Esse retorno é um **array direto**, sem `total` e `records`. O filtro `category` aceita `AUTHENTICATION`, `MARKETING`, `UTILITY` e `SERVICE`.

`POST /{id}/messages` envia texto, template ou arquivos pelo WhatsApp e aguarda o retorno imediato do provedor. Consulte `can_send_open_message` e `session_expires_at`: fora da janela de atendimento, use template.

```json theme={null}
{
  "type": "text",
  "body": "Olá, Maria. Podemos continuar seu atendimento?"
}
```

`type` assume `text` quando omitido. Para enviar um template, informe `type: "template"` junto com `template` e não envie `body`: com `body` preenchido, a API envia o texto e não o template.

Para responder a uma mensagem específica, acrescente `reference_wamid`, que aceita o identificador do WhatsApp ou o UUID local da mensagem. Nas rotas `/{id}/messages/{messageId}`, `messageId` é sempre o UUID local.

Uploads usam `multipart/form-data`, com arquivos nos campos `files` ou `file`, até 10 arquivos em cada campo. `template` e `template_fields` podem ser enviados como JSON serializado no formulário. O envio normal pode gerar uma mensagem de texto separada e uma mensagem por arquivo; leia todos os itens de `records`. `total` nesse retorno é a quantidade de mensagens enviadas pela operação. O envio manual também pode atribuir responsável e pausar um fluxo WhatsApp ativo.

Cada arquivo aceita até 100 MB, ou 16 MB quando é áudio. O `body` é enviado como texto separado e também como legenda de cada imagem, vídeo ou documento. A falha no envio de um arquivo não interrompe a operação: o item correspondente volta em `records` com `status: "failed"`, ainda com resposta `201`. Confira o `status` de cada item.

Em templates com mídia no cabeçalho, o `value` do campo `IMAGE`, `VIDEO` ou `DOCUMENT` aceita uma URL `http(s)` ou `file:<n>`, em que `n` é a posição, a partir de `0`, do arquivo enviado no mesmo formulário, contando primeiro os de `files` e depois os de `file`. Com `type: "template"`, os arquivos enviados servem apenas como mídia do cabeçalho e não geram mensagens separadas. Arquivo ausente, ou de tipo diferente do exigido pelo cabeçalho, retorna `400`.

Mensagens interativas e localização possuem rotas próprias:

| Operação | Corpo |
| - | - |
| `POST /{id}/messages/interactive` | `interactive_type`, `body`, `action`; opcionais `header`, `footer`, `reference_wamid`. |
| `POST /{id}/messages/location` | `latitude`, `longitude`; opcionais `name`, `address`, `reference_wamid`. |
| `POST /{id}/messages/typing` | `is_typing`; opcional `reference_wamid`. |

Exemplo de botões em `POST /{id}/messages/interactive`:

```json theme={null}
{
  "interactive_type": "button",
  "body": { "text": "Como deseja continuar?" },
  "action": {
    "buttons": [
      { "id": "ver_proposta", "title": "Ver proposta" },
      { "id": "falar_consultor", "title": "Falar com consultor" }
    ]
  }
}
```

`button` aceita de 1 a 3 botões em `action.buttons`. `list` exige `action.button` e `action.sections`, com no máximo 10 linhas no total. Não misture as duas estruturas; os IDs das opções devem ser únicos. O texto do corpo aceita até 1.024 caracteres; cabeçalho e rodapé, 60 cada. Localização aceita latitude de -90 a 90 e longitude de -180 a 180. Esses envios exigem janela de atendimento aberta.

<Warning>
  Na versão atual da API, `POST /{id}/messages/location` valida o corpo como mensagem interativa e retorna `400` ("Payload da mensagem interativa inválido.") mesmo com latitude e longitude válidas. Não dependa dessa rota até que o comportamento seja corrigido.
</Warning>

Para iniciar digitação, informe uma referência inbound das últimas 24 horas ou deixe o serviço localizar uma mensagem elegível recente. Com `is_typing=false`, o retorno é uma confirmação local com `reference_wamid=null`.

<Note>
  A consulta de chats e mensagens já é multicanal, mas o envio externo síncrono, criação manual, templates, interativos, localização e digitação descritos acima usam WhatsApp. Não assuma que uma conversa Instagram listada aceita essas operações.
</Note>

## Atendimento, pessoas e responsáveis

| Operação | Resultado |
| - | - |
| `GET /notifications/unread` | Agrega `unread_messages_total` e `unread_chats_total` de WhatsApp e Instagram, sem contar conversas arquivadas. |
| `POST /{id}/read` | Zera mensagens não lidas e remove a marcação manual. |
| `POST /{id}/unread` | Ativa a marcação manual de não lido. |
| `PATCH /{id}/status` | WhatsApp: altera `status`; `reason` é opcional. |
| `PATCH /{id}/priority` | WhatsApp: altera `priority`, de 0 a 3. |
| `PATCH /{id}/archive` | Arquiva uma conversa WhatsApp. |
| `PATCH /{id}/unarchive` | Desarquiva uma conversa WhatsApp. |
| `GET /{id}/assignable-agents` | Lista agentes elegíveis para o número ou conta do chat. |
| `POST /{id}/participants` | WhatsApp: adiciona participante com `user_id`. |
| `DELETE /{id}/participants/{userId}` | WhatsApp: remove participante; o responsável atual não pode ser removido. |
| `POST /{id}/create-person` | Cria uma pessoa ou vincula pessoa existente, por `person_id`. |
| `PATCH /{id}/responsible` | Atualiza responsável, com propagação opcional para leads e oportunidades. |

`create-person` exige **ambas** as permissões `crm/chats.update` e `crm/person.create`, mesmo quando vincula uma pessoa existente. Sem `person_id`, envie `name`; também aceita `birth_date`, `gender`, `notes`, `contacts`, `documents`, `address` e `addresses`. O serviço vincula o contato do canal à pessoa.

Exemplo de troca do responsável:

```json theme={null}
{
  "user_id": "f7096f62-32ef-4d73-8e22-f939d1fa87d4",
  "update_chat": true,
  "update_leads": true,
  "update_deals": true
}
```

`update_chat` assume `true`; `update_leads` e `update_deals`, `false`. A propagação atualiza os registros abertos, não arquivados e não excluídos associados à pessoa do chat. Quando solicitada, exige também `crm/lead.update` e/ou `crm/deal.update` na chave. Essas mutações retornam os detalhes do chat; alguns enriquecimentos da consulta, como `assignable_agents`, podem ser omitidos.

## Reações, exclusão e edição

Use `POST /{id}/messages/{messageId}/reaction` com `{ "emoji": "👍" }` para reagir e `DELETE` no mesmo caminho para remover a reação da empresa. O retorno é a mensagem atualizada; as rotas suportam WhatsApp e Instagram conforme as regras de acesso e do provedor. No Instagram, só são aceitas as reações `love`, `like`, `dislike`, `smile`, `angry`, `sad` e `wow`, informadas pelo nome ou pelo emoji correspondente; qualquer outra retorna `400`.

`DELETE /{id}/messages/{messageId}` solicita exclusão de uma mensagem WhatsApp enviada pela empresa. Mensagens inbound não são elegíveis. Se a Meta recusar a exclusão, a API retorna `400`; quando aceita, retorna a mensagem com `status=deleted`.

<Warning>
  `PATCH /{id}/messages/{messageId}` está exposto, mas a edição de mensagens enviadas não está implementada pelo provedor. A API valida o acesso, registra a tentativa e retorna `400` com a mensagem: “A API oficial da Meta não suporta edição de mensagens enviadas via WhatsApp Business Platform.” Não trate essa operação como uma atualização bem-sucedida.
</Warning>

## Mensagens agendadas

`POST /{id}/scheduled-messages` cria um agendamento WhatsApp. Informe `scheduled_at` no futuro, com fuso horário, e conteúdo: `body`, anexos ou `template`. `type` aceita `text` ou `template`; se omitido, é inferido pela presença de `template`.

```json theme={null}
{
  "scheduled_at": "2027-01-20T14:00:00-03:00",
  "cancel_on_inbound": true,
  "type": "template",
  "template": {
    "name": "retomar_atendimento",
    "language": "pt_BR"
  }
}
```

Substitua a data e o nome do template pelos valores do seu envio. Texto aberto e anexos só podem ser agendados até `session_expires_at`; após a janela, use template. Com `cancel_on_inbound=true`, uma interação inbound cancela o envio pendente; o padrão é `false`.

| Operação | Comportamento |
| - | - |
| `GET /{id}/scheduled-messages` | Lista com `skip`, `take` e `status`, por horário crescente; `search` é aceito, mas não filtra os registros. |
| `PATCH /{id}/scheduled-messages/{scheduledMessageId}` | Edita somente agendamentos `PENDING` que não tenham sido criados por um agente de IA. |
| `POST /{id}/scheduled-messages/{scheduledMessageId}/cancel` | Cancela somente `PENDING`; aceita `reason` opcional. |

Na edição, campos ausentes preservam o valor anterior, inclusive `type`. Novos arquivos substituem todos os anexos; `replace_files=true` sem arquivos limpa os anexos. Criação e edição aceitam JSON ou multipart, seguindo os mesmos campos de upload de mensagens.

Agendamentos criados por um agente de IA aparecem na listagem com `whatsapp_ai_agent_id` preenchido. Eles podem ser cancelados, mas a edição retorna `400`: cancele e crie um novo agendamento.

Os retornos incluem `is_scheduled`, `status`, `message_kind`, `payload`, `attachments`, `scheduled_at`, `sent_at`, `canceled_at`, `failure_reason` e `sent_message_ids`. Os estados são `PENDING`, `PROCESSING`, `SENT`, `CANCELED` e `FAILED`. Cancelamentos informam `cancel_reason` e `cancel_reason_description`.

## Permissões e status HTTP

| Ação | Permissão da chave |
| - | - |
| Consultas | `crm/chats.read` |
| Criação manual da conversa | `crm/chats.create` |
| Envio, digitação e agendamentos | `crm/chats.write` |
| Atendimento, participantes, responsável, edição e reações | `crm/chats.update` |
| Exclusão de mensagem | `crm/chats.delete` |
| Criação/vínculo de pessoa | `crm/chats.update` e `crm/person.create` |

Os `POST` bem-sucedidos retornam `201`, inclusive ações como marcar lido, aplicar reação e cancelar agendamento. `GET`, `PATCH` e `DELETE` retornam `200` quando a operação tem sucesso. A exceção de edição de mensagens descrita acima retorna erro. Consulte os schemas completos de cada operação na seção **Rotas da API**.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.