# Sincronização de histórico

**Evento:** `history` · **Transporte:** POST para o seu receptor

Receba lotes de dados processados durante sincronizações e recuperações de histórico.

## Variações do payload

`EventType` permanece `history`. O campo `event` identifica o conteúdo do lote: por exemplo `messages`, `chats`, `calls`, `labels` ou `chat_labels`. Leia o array correspondente; não suponha que todos os arrays existam no mesmo evento.

Sincronizações de etiquetas podem acrescentar `history_type`, `sync_id`, `full_sync`, `summary` e `chunk`. Esses metadados não são universais para todo histórico.

## Como processar

Faça upsert pelos IDs, aceite vários lotes e tolere sobreposição com eventos ao vivo. O recebimento de um lote não comprova que todo o histórico do WhatsApp foi sincronizado. Quando `chunk.has_more` existir, ele descreve aquela sequência de chunks.

## Sequências e conclusão

Cada origem de lotes recebe um `batchChunkOrder`: o histórico inicial, cada parte que o WhatsApp envia depois dele e cada resposta de `POST /message/history-sync`. Chats, mensagens e ligações da mesma origem compartilham o número. Identifique uma sequência por `batchChunkOrder` + `event` e acompanhe seus lotes com `batchNumber` e `batchTotal`. Lotes de sequências diferentes podem chegar intercalados.

Lotes com dados chegam com `batchHistoryStatus: "loading"`. O fim é informado por um lote sem dados, com `event: "status"` e `batchHistoryStatus: "complete"`; seu `batchChunkOrder` é o da última sequência enviada. Ele sai quando o WhatsApp indica o fim da sincronização completa ou após cerca de 2 minutos sem novas partes do histórico. Se partes atrasadas chegarem depois, um novo `complete` é enviado: considere o de maior `batchChunkOrder`. A numeração recomeça em 1 a cada pareamento.

Um novo pareamento pode reenviar mensagens já recebidas. Deduplique por `messageid` e faça upsert pelos IDs: lotes também podem se sobrepor a eventos recebidos ao vivo.

## Habilitar este evento

Adicione `history` à lista `events` do webhook da instância. Preserve os outros eventos de que sua integração precisa.

```json
{
  "enabled": true,
  "url": "https://seu-sistema.example/hooks/whatsapp",
  "events": [
    "history"
  ]
}
```

Envie essa configuração para [POST /webhook](/reference/updateWebhook.md), usando o header `token`. O JSON acima configura a assinatura; os exemplos de entrega abaixo são o que seu servidor recebe.

## Campos do payload

O envelope comum vem na raiz. Campos condicionais podem estar ausentes ou nulos conforme o evento; não use a tabela como obrigação de presença de todos os campos.

| Campo | Tipo | Significado |
|---|---|---|
| `EventType` | string | **Obrigatório.** Tipo de evento, por exemplo connection ou messages. |
| `owner` | string | **Obrigatório.** Consulte o objeto ou exemplo correspondente. |
| `token` | string | **Obrigatório.** Token da instância; dado sensível. |
| `BaseUrl` | string | **Obrigatório.** Consulte o objeto ou exemplo correspondente. |
| `instanceName` | string | Consulte o objeto ou exemplo correspondente. |
| `event` | string | Conteúdo do lote: messages, chats, calls, labels, chat_labels ou status (conclusão do histórico). |
| `messages` | array / null | Lote de mensagens. |
| `messages[].id` | string | Identificador retornado pelo sistema; preserve como string. |
| `messages[].messageid` | string | ID da mensagem no WhatsApp. |
| `messages[].chatid` | string | JID do contato, grupo ou canal. |
| `messages[].sender` | string | JID do remetente. |
| `messages[].senderName` | string | Nome disponível do remetente. |
| `messages[].fromMe` | boolean | Mensagem enviada pela conta conectada. |
| `messages[].wasSentByApi` | boolean | Origem na API quando esse campo estiver presente na mensagem. |
| `messages[].isGroup` | boolean | Identifica conversa de grupo. |
| `messages[].messageType` | string | Tipo de mensagem normalizado. |
| `messages[].text` | string | Texto ou legenda disponível. |
| `messages[].messageTimestamp` | integer | Timestamp da mensagem em milissegundos Unix. |
| `messages[].content` | variável | Conteúdo específico do tipo de mensagem; não possui um formato único. |
| `messages[].status` | string | Estado disponível da mensagem; pode estar vazio. |
| `chats` | array / null | Lote de chats. |
| `chats[].id` | string | ID local do chat. |
| `chats[].wa_chatid` | string | JID da conversa. |
| `chats[].name` | string | Nome disponível. |
| `chats[].wa_isGroup` | boolean | Conversa de grupo. |
| `chats[].wa_isBlocked` | boolean | Estado de bloqueio no snapshot. |
| `chats[].wa_archived` | boolean | Estado de arquivamento. |
| `chats[].wa_unreadCount` | integer | Quantidade de mensagens não lidas disponível. |
| `chats[].wa_label` | variável | Etiquetas associadas, conforme a projeção do chat. Pode ser texto JSON; normalize antes de usar. |
| `labels` | array / null | Lote de etiquetas. |
| `chat_labels` | array / null | Associações atualizadas pela sincronização de etiquetas. |
| `sync_id` | string | Correlação da sincronização de etiquetas, quando presente. |
| `history_type` | string | Origem adicional, como labels_refresh. |
| `full_sync` | boolean | Se a sincronização de etiquetas foi completa. |
| `chunk` | object | Metadados opcionais de fragmentação. |
| `chunk.index` | integer | Índice do chunk. |
| `chunk.total` | integer | Total daquela sequência. |
| `chunk.size` | integer | Itens neste chunk. |
| `chunk.has_more` | boolean | Existem mais chunks naquela sequência. |
| `batchNumber` | integer | Número deste lote, começando em 1. |
| `batchTotal` | integer | Total de lotes desta sequência. |
| `batchChunkOrder` | integer | Sequência da origem deste lote, atribuída pela API. Não é a ordem do chunk no WhatsApp e recomeça em 1 a cada pareamento. |
| `batchHistoryStatus` | string | `loading` em lotes com dados; `complete` no lote `status` que encerra o histórico. |
| `calls` | array / null | Registros de chamadas do histórico quando event=calls. |

## Exemplos de entrega

Exemplos ilustrativos com identificadores fictícios. O conteúdo específico e os campos opcionais variam.

### Lote de mensagens

```json
{
  "EventType": "history",
  "owner": "5511999999999",
  "token": "INSTANCE_TOKEN",
  "BaseUrl": "https://seu-servidor.example",
  "instanceName": "Atendimento",
  "event": "messages",
  "messages": [
    {
      "id": "5511999999999:MSG_HISTORICO",
      "messageid": "MSG_HISTORICO",
      "chatid": "5511888888888@s.whatsapp.net",
      "text": "Mensagem do histórico",
      "messageTimestamp": 1788868800000
    }
  ],
  "batchNumber": 1,
  "batchTotal": 1,
  "batchChunkOrder": 1,
  "batchHistoryStatus": "loading"
}
```

### Lote de chats

```json
{
  "EventType": "history",
  "owner": "5511999999999",
  "token": "INSTANCE_TOKEN",
  "BaseUrl": "https://seu-servidor.example",
  "instanceName": "Atendimento",
  "event": "chats",
  "chats": [
    {
      "id": "r0123456789abcd",
      "wa_chatid": "5511888888888@s.whatsapp.net",
      "name": "Contato de exemplo"
    }
  ],
  "batchNumber": 1,
  "batchTotal": 1,
  "batchChunkOrder": 1,
  "batchHistoryStatus": "loading"
}
```

### Conclusão do histórico

```json
{
  "EventType": "history",
  "owner": "5511999999999",
  "token": "INSTANCE_TOKEN",
  "BaseUrl": "https://seu-servidor.example",
  "instanceName": "Atendimento",
  "event": "status",
  "batchNumber": 1,
  "batchTotal": 1,
  "batchChunkOrder": 3,
  "batchHistoryStatus": "complete"
}
```

## Responder ao webhook

Seu receptor deve aceitar o POST JSON e devolver uma resposta `2xx` rapidamente, após validar e registrar o recebimento. O corpo da resposta não é um comando para a API. Processe trabalho demorado separadamente.

O worker não repete automaticamente uma entrega HTTP malsucedida. Consulte [diagnóstico de webhooks](/docs/integrations-webhooks#diagnostico) e implemente a reconciliação necessária. Eventos repetidos ou fora de ordem ainda precisam ser tolerados pelo receptor.

## Referências

- [Introdução, configuração e catálogo](/docs/integrations-webhooks)
- [Autenticação](/docs/authentication)
- [Contrato OpenAPI completo](/openapi-bundled.json)
