Resposta curta: na coexistência, os contatos da agenda e as conversas antigas do aplicativo não aparecem sozinhos na API. São duas chamadas para POST /v1/{phone_number_id}/smb_app_data, uma para contatos e outra para histórico, e cada uma pode ser disparada uma vez só. E existe um prazo que não perdoa: 24 horas a partir da conexão do número. Passou disso, só refazendo o onboarding, e desconectar o número só é possível pelo celular. Antes de qualquer chamada, dois pré-requisitos: o cliente precisa ter autorizado o compartilhamento na tela do celular e os eventos history e smb_app_state_sync precisam estar marcados no webhook.
Principais pontos
- Não é automático. Conectar o número em coexistência não traz contato nem conversa. É preciso pedir.
- O prazo conta da conexão. São 24 horas após o onboarding. Nas palavras de Israel Henrique, CTO da Datafy: "isso tem que ser feito em até 24 horas após você fazer a conexão. Se passou de 24 horas, não dá mais. Aí tem que desconectar e conectar de novo."
- Uma vez por tipo.
smb_app_state_syncehistorysão disparos únicos por integração. Não existe segunda tentativa. - Os dados chegam pelo webhook, não na resposta. A chamada devolve um
request_ide pronto. O conteúdo vem em eventos assíncronos. - O histórico chega em fases sobrepostas, com pedaços fora de ordem e duplicatas. Junte por conversa, remova repetidas pelo
wamide ordene por horário.
Não confunda as duas janelas de 24 horas
Antes de tudo, uma distinção que causa confusão em quase toda integração nova: existem duas coisas diferentes com o número 24 na API oficial.
| Qual janela | O que ela controla | O que a reinicia |
|---|---|---|
| Janela de atendimento | Se você pode responder o cliente sem template | Cada nova mensagem do cliente |
| Prazo de sincronização | Se você ainda pode pedir contatos e histórico do aplicativo | Nada. Ela conta da conexão e não renova |
A janela de atendimento é renovável e acontece milhares de vezes. O prazo de sincronização acontece uma vez na vida daquela conexão. Tratar os dois como a mesma coisa é o erro que faz alguém descobrir, uma semana depois, que perdeu o histórico do cliente.
Antes de disparar: os três pré-requisitos
1. O compartilhamento foi autorizado no celular. Durante a conexão, depois de tocar em conectar na mensagem do Facebook e na tela conectar plataforma comercial, o aplicativo pergunta se você deseja compartilhar o histórico de conversas e mensagens. Marcar sim é o que habilita tudo o que vem depois. Marcou não? Não há chamada que resolva: é refazer a conexão. O fluxo completo de conexão está aqui.
2. Os eventos estão assinados no webhook. No painel, abra o número, vá na aba de webhooks e marque history e smb_app_state_sync na lista de eventos daquela URL. Isso precisa estar feito antes do disparo, porque os dados chegam por esses eventos e não ficam guardados esperando você assinar.
3. Você está dentro das 24 horas. O relógio começa no onboarding. A documentação da Meta diz a mesma coisa que o vídeo: sem sincronizar nesse prazo, o cliente precisa ser desconectado e refazer o fluxo. E a desconexão é feita no celular, em Configurações, Conta, Plataforma do WhatsApp Business, Desconectar. Não existe desconexão pela API, e as rotas de deregister são bloqueadas por segurança.
Na prática, isso inverte a ordem natural do trabalho: o webhook e o código que recebe precisam estar prontos antes de escanear o QR code, não depois.
Passo 1: descobrir o seu phone_number_id
O endpoint de sincronização é por número, então a primeira chamada é a que devolve os identificadores:
GET https://cloud.datafyapi.com.br/me
Authorization: Bearer sk_live_xxx
{
"cliente_id": "uuid-do-cliente",
"phone_number_id": "106540352242922",
"waba_id": "366634483210360",
"business_id": "123456789"
}
Passo 2: pedir os contatos
Contatos primeiro, porque é o disparo que responde mais rápido:
POST https://cloud.datafyapi.com.br/v1/106540352242922/smb_app_data
Authorization: Bearer sk_live_xxx
Content-Type: application/json
{
"messaging_product": "whatsapp",
"sync_type": "smb_app_state_sync"
}
{
"messaging_product": "whatsapp",
"request_id": "7a3b2c1d-e5f6-4a8b-9c0d-1e2f3a4b5c6d",
"success": true
}
Guarde o request_id. Ele é o identificador daquele pedido junto ao suporte da Meta, e é a única coisa que você tem na mão se a entrega falhar. Anote junto a data, o número e o tipo.
Passo 3: pedir o histórico
Mesma rota, mesmo cabeçalho, muda uma palavra:
{
"messaging_product": "whatsapp",
"sync_type": "history"
}
E vale repetir, porque é o detalhe que mais custa: cada sync_type só pode ser disparado uma vez por integração. Não existe repetir para conferir, nem disparar em ambiente de teste e depois em produção com a mesma conexão.
Como os contatos chegam
Pelo evento smb_app_state_sync, quase sempre num único webhook, com tudo dentro do array state_sync. Contas com agenda muito grande podem gerar vários, sem ordem garantida.
{
"field": "smb_app_state_sync",
"value": {
"messaging_product": "whatsapp",
"state_sync": [
{
"type": "contact",
"action": "add",
"contact": {
"phone_number": "5511999999999",
"full_name": "Israel Henrique",
"first_name": "Israel"
},
"metadata": { "timestamp": "1759100000000" }
}
]
}
}
Dois detalhes que quebram código:
A ação diz o que fazer. add serve para adicionar e também para atualizar um contato existente. remove é remoção. Tratar add como insert puro gera erro de chave duplicada na segunda leva.
O timestamp está em milissegundos, com 13 dígitos. O do histórico vem em segundos, com 10. Passar os dois pela mesma função de conversão dá datas em 1970 num dos lados, e é o erro clássico de quem processa os dois eventos no mesmo handler.
A boa notícia: depois da sincronização inicial, as alterações futuras na agenda continuam chegando por esse mesmo evento, automaticamente, sem chamar o endpoint de novo. O disparo único vale para a carga inicial.
Como o histórico chega
Pelo evento history, em vários webhooks assíncronos, cada um podendo carregar muitas mensagens. A estrutura é aninhada em três níveis:
1 POST no seu webhook
└── value.history[]
└── threads[] 1 thread = 1 conversa com 1 contato
└── messages[] as mensagens daquela conversa
Quatro comportamentos precisam estar previstos no seu código, senão o histórico importado sai errado:
Fases. São três, contadas a partir da conexão: fase 0 do dia 0 ao 1, fase 1 do dia 1 ao 90, fase 2 do dia 90 ao 180. Isso dá até 180 dias de histórico. As fases se sobrepõem: mensagem de qualquer data pode aparecer em qualquer fase. Nunca deduza o período pela fase. Ordene pelo timestamp.
Pedaços. Cada fase vem em vários chunk_order, e não necessariamente em ordem. O campo progress vai de 0 a 100, e progress: 100 na última fase é o sinal de que acabou.
Duplicatas são garantidas. O mesmo thread.id aparece em vários webhooks, e a mesma mensagem pode vir repetida. A regra obrigatória: colete tudo do mesmo thread, remova duplicatas pelo wamid e ordene por horário. O cabeçalho x-datafy-delivery-id de cada entrega ajuda como chave de idempotência do webhook, mas não substitui o dedup por mensagem.
Direção. history_context.from_me com valor true é mensagem enviada pela empresa. Ausente ou falso, é mensagem recebida. É por esse campo que você decide de que lado da tela o balão aparece.
A mídia do histórico é um caso separado
Aqui está a limitação que mais decepciona quem esperava recuperar tudo: a mídia não vem dentro das conversas. Ela aparece como type: "media_placeholder", sem conteúdo.
O arquivo, quando existe, chega em webhooks separados, em value.messages ou em value.message_echoes, e você casa com a conversa pelo wamid. E só as mídias de até 14 dias antes do onboarding têm arquivo disponível, segundo a documentação da Meta. Uma foto enviada há três meses volta como marcador, e nada recupera o arquivo.
Quando o arquivo existe, o caminho é o mesmo de qualquer mídia recebida:
GET https://cloud.datafyapi.com.br/media/1037543291543636
Authorization: Bearer sk_live_xxx
{
"url": "https://files.datafyapi.com.br/uuid-cliente/2026/09/1759100000000-a1b2c3d4.jpg",
"mime_type": "image/jpeg",
"size": 86620
}
A URL devolvida vale 30 dias. Se o seu produto vai exibir o histórico por mais tempo, baixe e guarde no seu armazenamento. Como receber mídia está aqui.
Quando acontece o quê
| Quando | O que acontece |
|---|---|
| Você conecta o número e autoriza o compartilhamento no celular | Nada chega ainda. O relógio de 24 horas começa |
Você dispara smb_app_state_sync |
Os contatos chegam logo, quase sempre num webhook só |
Você dispara history |
As conversas começam a chegar em fases e pedaços, e podem levar vários minutos |
| Você dispara o mesmo tipo de novo | Não vai acontecer nada de novo. O disparo é único por tipo |
| Passaram as 24 horas | Não há mais como pedir. É desconectar pelo celular e refazer o onboarding |
| Depois da carga inicial, o cliente muda um contato na agenda | A alteração chega sozinha, pelo mesmo evento de contatos |
| Uma mensagem nova entra pelo celular | Chega como smb_message_echoes, que é outro evento, e não faz parte da sincronização |
A linha de tempo do histórico é a que mais gera dúvida. A documentação da Meta diz que pode levar vários minutos, dependendo do tamanho do histórico, da internet e da velocidade com que você consome os webhooks, e não publica prazo fixo. Não refaça nada porque nada apareceu em dois minutos: o disparo é único e você não terá uma segunda chance.
O que muda com a Datafy, e o que não muda
Não muda: o prazo de 24 horas, o disparo único, as fases, as duplicatas, o teto de 180 dias, o limite de 14 dias para mídia e a desconexão pelo celular são todos regra da Meta.
Muda o acesso à coexistência. Oferecer o modo em que o aplicativo continua no celular e a API trabalha no mesmo número depende de ser parceiro de tecnologia homologado. É o que a Datafy é, e é isso que coloca a opção de conectar um aplicativo existente no fluxo de conexão.
Muda o preparo. Os eventos são marcados na tela, por número, e o webhook chega com assinatura HMAC nos cabeçalhos, o que resolve a parte de confiar no que você recebe antes de gravar 180 dias de conversa no seu banco.
Muda a mídia do histórico, que é a parte mais chata: em vez de lidar com arquivo criptografado, você chama a rota simplificada e recebe uma URL pronta.
Perguntas frequentes
Passou das 24 horas. Tem como recuperar o histórico?
Só desconectando o número pelo celular e refazendo o onboarding. A desconexão não existe pela API, e as rotas de deregister são bloqueadas.
Posso disparar a sincronização mais de uma vez?
Não. Cada sync_type é disparo único por integração. Por isso a recomendação de ter o webhook e o consumidor prontos antes de conectar o número.
Quanto tempo de histórico vem?
Até 180 dias, em três fases. Como as fases se sobrepõem, não use a fase para deduzir data: ordene pelo horário de cada mensagem.
As mídias antigas vêm junto?
Só as de até 14 dias antes do onboarding têm arquivo. As demais aparecem como marcador, sem conteúdo, e não há como recuperá-las depois.
Por que as datas dos contatos ficaram erradas no meu banco?
Provavelmente porque o timestamp dos contatos vem em milissegundos e o do histórico em segundos. São 13 dígitos contra 10, e a mesma função de conversão não serve para os dois.
Preciso sincronizar para o atendimento funcionar?
Não. A sincronização traz o passado. Mensagem nova chega normalmente, e a que sai do celular aparece pelo evento de eco de mensagens. Como isso aparece num inbox pronto está aqui.
Os contatos novos continuam chegando depois?
Continuam. Depois da carga inicial, as alterações na agenda do aplicativo seguem chegando pelo evento de contatos, sem nova chamada.
Como decidir
Se o histórico daquele número importa, e na maioria dos atendimentos importa, trate a sincronização como parte do onboarding, não como tarefa para depois. A ordem que funciona é esta: cadastre o webhook, marque history e smb_app_state_sync, deixe pronto o código que junta por thread, remove duplicata pelo wamid e ordena por horário, e só então conecte o número. Assim as duas chamadas viram o passo seguinte da conexão, feito em minutos.
Se o histórico não importa, ainda vale disparar os contatos: é uma requisição, chega rápido e economiza um trabalho de cadastro manual que ninguém quer fazer. E se você está atendendo clientes de terceiros, coloque a autorização no celular como item de checklist do onboarding, porque é a etapa que o cliente pode recusar sem entender o que está recusando.
Deixe o webhook pronto antes de escanear o QR code
Cadastre a URL no painel, marque history e smb_app_state_sync, conecte o número autorizando o compartilhamento no celular, chame GET https://cloud.datafyapi.com.br/me e dispare os dois sync_type em seguida, guardando os dois request_id.
Sem taxa de setup · Cancele quando quiser · Suporte por WhatsAppLeia também
- Como conectar um número na API oficial do WhatsApp
- Como usar a API oficial do WhatsApp no Chatwoot
- Como receber mídia na API oficial do WhatsApp
- Como ver o payload das mensagens em tempo real
Continue por aqui
- ImplementaçãoComo conectar um número na API oficial do WhatsApp em 5 minutos, sem burocracia
O passo a passo completo da conexão: criar o número no painel, escolher o portfólio empresarial, chip novo ou aplicativo existente, escanear o QR code e cadastrar a forma de pagamento na BM.
Ler mais - ImplementaçãoComo criar um template de WhatsApp passo a passo, no painel da Meta
Gerenciar modelos, categoria, cabeçalho com imagem, corpo com variáveis e exemplo obrigatório, botões e envio para análise. E o que a categoria faz no seu custo.
Ler mais - ImplementaçãoComo enviar imagem, documento e áudio pela API oficial do WhatsApp
Por link ou por identificador, no mesmo endpoint de mensagens. Legenda na imagem, nome no documento, e o que faz o áudio virar bolha de voz em vez de anexo.
Ler mais