Enviar e receber
Histórico de conversas
Quando um número é pareado, o WhatsApp entrega ao Nuntis as conversas que já existiam naquele aparelho. O Nuntis guarda esse histórico e o expõe pela API — mas não o anuncia por webhook. Esta página explica de onde ele vem, por que chega em silêncio, e como trazê-lo para o seu produto.
1. De onde vem o histórico
Há dois momentos em que mensagens anteriores ao pareamento entram no Nuntis:
| Quando | O que entra | Como |
|---|---|---|
| No pareamento (desde 02/09/2026) | As conversas recentes que o WhatsApp envia ao aparelho recém-pareado — o mesmo lote que o WhatsApp Web recebe ao ler o QR. | Automático. Nenhuma ação sua. |
| Uma única vez, em 01–02/09/2026 | Para os números pareados antes dessa data, o histórico que o canal ainda tinha disponível foi importado retroativamente. | Feito pela Devari. Não se repete. |
O que o WhatsApp envia no pareamento é decidido pelo WhatsApp, não pelo Nuntis: é um recorte das conversas mais recentes, e o tamanho desse recorte varia por conta. O Nuntis não pede mais do que isso ao canal — pedir histórico adicional ao WhatsApp é um sinal que expõe o número, e o Nuntis não emite esse sinal em nome de ninguém.
2. Histórico não dispara webhook — de propósito
Um pareamento pode trazer dezenas de milhares de mensagens de uma vez. Cada
uma delas é antiga: já foi lida, já foi respondida, já
aconteceu. Anunciar cada uma como message.received entregaria ao
seu endpoint uma avalanche de eventos sobre fatos passados, indistinguível de
tráfego novo — e a reação natural de um CRM (notificar o vendedor, abrir
atendimento, disparar automação) seria errada em todas elas.
Por isso o histórico entra em silêncio: fica gravado na conversa, com a data real em que cada mensagem foi enviada, e aparece na leitura pela API. Nenhum dos cinco eventos de webhook é emitido para ele.
A consequência prática é uma decisão de arquitetura do seu lado: o webhook é um aviso de que algo aconteceu agora; a API é a fonte. Um produto que mantém cópia local das mensagens alimentada apenas por webhook está, por construção, cego para tudo o que não é tempo real — histórico do pareamento, eventos perdidos numa janela de indisponibilidade do seu endpoint, correções. Se a cópia local existe, ela precisa ser ressincronizada a partir da API, e a seção seguinte mostra como.
3. Ler o histórico pela API
GET /v1/messages
Lista mensagens de todas as conversas de todos os números do seu tenant, em ordem cronológica crescente, paginadas por cursor. Aceita três parâmetros:
| Parâmetro | Efeito |
|---|---|
since | Cursor opaco devolvido em cursor.next da página anterior. Repasse sem interpretar. Ausente = do início. |
conversationId | Restringe a uma conversa. Sem ele, a listagem abrange o tenant inteiro. |
limit | Itens por página, de 1 a 100. Padrão 50. |
# primeira página: sem cursor
curl -H "x-api-key: $NUNTIS_API_KEY" \
"https://api.nuntis.com.br/v1/messages?limit=100"
# páginas seguintes: repasse cursor.next até ele vir null
curl -H "x-api-key: $NUNTIS_API_KEY" \
"https://api.nuntis.com.br/v1/messages?limit=100&since=eyJjIjoi..."
{
"data": [
{
"id": "msg_18273",
"conversationId": "conv_991",
"numberId": "num_7",
"direction": "inbound",
"type": "text",
"from": { "phoneE164": "+5585999998888", "pushname": "Ana" },
"text": { "body": "Bom dia, ainda tem vaga?" },
"timestamp": "2026-06-14T13:02:11.000Z",
"timestampUnix": 1781485331,
"status": "received"
}
],
"cursor": { "next": "eyJjIjoiMjAyNi0wNi0xNFQxMzowMjoxMS4wMDBaIn0" }
}
O cursor que você guardou não alcança o histórico
O cursor é posicional: marca um ponto na linha do tempo e a página seguinte traz o que vem depois dele. O histórico entra com a data real de cada mensagem — que é anterior ao ponto onde o seu cursor parou. Continuar paginando de onde você estava, portanto, nunca chega ao histórico: ele ficou para trás.
Para trazê-lo, faça uma varredura a partir do início — sem
since — ou por conversa, com conversationId, que
também começa do início daquela conversa. Deduplique pelo id da
mensagem: é o mesmo identificador que chega em data.id no
webhook e em GET /v1/messages/{id}, estável para sempre. Uma
mensagem que você já tem é ignorada; uma que você não tem é histórico (ou
evento perdido — e a cura é a mesma).
Quando fazer a varredura
-
Depois de cada pareamento. Observe
GET /v1/numbers/{id}/statusatéconnected. O WhatsApp entrega o histórico nos minutos seguintes; uma varredura alguns minutos depois deconnectedo encontra. O contrato ainda não expõe um sinal de "histórico concluído" — se uma varredura vier incompleta, repita mais tarde; a deduplicação peloidtorna a repetição barata. - Uma vez agora, para os números que já estavam em operação antes de 02/09/2026 e receberam o histórico importado.
- Sempre que o seu endpoint de webhook tiver ficado fora do ar por mais tempo do que a janela de retentativa descrita em Garantias de entrega.
4. O que vem no histórico, e o que não vem
| Tipo | Situação |
|---|---|
| Texto | Completo, com a data real de envio em timestamp. |
| Mídia (imagem, áudio, vídeo, documento) | Metadados sempre. O arquivo, quando o WhatsApp ainda o serve; quando não serve mais, a mensagem vem com media.pending: true — ver Mídia. |
| Mensagens de grupo | Entram como conversa própria, com o bloco group preenchido e from apontando para o participante que falou. Nunca dentro da conversa individual de quem falou. |
| Mensagens enviadas pelo próprio número | Entram com direction: "outbound", inclusive as que saíram pelo aparelho e não pelo Nuntis. |
| Reação e enquete | Chegam como envelope, sem bloco de conteúdo — o contrato ainda não tem campo para eles. Lacuna reconhecida. |
timestamp é quando a mensagem foi enviada, não quando o Nuntis a recebeu
Uma mensagem de março chega ao Nuntis em setembro, no pareamento, e sai na API com a data de março. É isso que permite montar a conversa na ordem em que ela aconteceu. Não use a hora em que você leu a mensagem como data dela.
Rotas desta página
| Rota | Uso |
|---|---|
GET /v1/messages | Varredura cronológica, por cursor; filtro por conversa. |
GET /v1/messages/{id} | Uma mensagem, com o histórico de status. |
GET /v1/numbers/{id}/status | Saber que o pareamento concluiu antes de varrer. |