Implementação

O telefone está sumindo do webhook: como usar o user_id na API oficial do WhatsApp

Migração de provedor mantendo o mesmo número Ilustração de um número de telefone que permanece o mesmo enquanto a conexão muda de um provedor para outro. antes depois o número continua seu muda a URL e o token

Resposta curta: o WhatsApp ganhou nome de usuário, aquele identificador no estilo do Instagram que já aparece no aplicativo, e na API ele chega como user_id. O efeito prático é que o telefone da pessoa deixa de vir no webhook, de forma progressiva, e quem usa o número como chave única fica sem chave. Para responder alguém pelo user_id, o corpo do envio troca o campo to por recipient, com o valor que veio dentro de messages. E há um detalhe que muda a modelagem do seu banco antes de mudar o seu código: o user_id não é a identidade da pessoa, é a identidade da relação entre aquela pessoa e a sua empresa.

1 campoto dá lugar a recipient no envio
1 relaçãoo user_id vale entre a pessoa e a sua empresa
4 statussent, delivered, read e failed continuam chegando
3 webhooksé o que um envio bem-sucedido gera em status

Principais pontos

O que está mudando

O nome de usuário já aparece no aplicativo e funciona como o arroba do Instagram: dá para falar com alguém sem saber o número dela. Quem troca de chip mantém o mesmo nome de usuário, e quem não quer expor o telefone passa a ter como não expor.

Na API isso se traduz numa mudança silenciosa: o número de quem enviou a mensagem para de aparecer no webhook. Israel Henrique, CTO da Datafy, é direto sobre o ritmo disso: "o número da pessoa vai parar de aparecer num dado momento. Isso é progressivo, está acontecendo aos poucos."

Uma ressalva importante, e ela é do próprio autor: o final de 2026 aparece como expectativa, não como prazo publicado. A recomendação técnica não depende da data. Depende de você não ter o telefone como única chave no dia em que ele não vier.

O erro de modelagem que quase todo mundo comete

Esse é o trecho que vale mais que o código. O user_id não é universal. Ele identifica um par: aquela pessoa e aquela empresa.

Quando O que acontece com o identificador
João manda mensagem para o seu número Existe um user_id que representa a relação entre você e o João
João troca de número de telefone O nome de usuário dele continua o mesmo, e a relação com você também
João manda mensagem para outra empresa Naquela conversa o user_id dele é outro, sem relação com o seu
Você conecta um segundo número na mesma conta Trate o identificador como chave dentro daquele contexto, não como identidade global

Nas palavras dele: "eu tenho o meu WhatsApp Business, o João entrou em contato comigo, o user ID do João vai ser um entre eu e ele. Se o João entrar em contato com outro WhatsApp Business, uma outra empresa, o user ID do João vai ser outro."

A consequência prática é direta. Se você está construindo um SaaS multiempresa, o user_id não pode ser a chave primária de pessoa na sua base. Ele é a chave de contato dentro de uma conta. A pessoa física que fala com dez clientes seus tem dez identificadores diferentes, e nenhum sistema no mundo consegue dizer que são a mesma pessoa a partir deles. Quem modela ao contrário descobre isso quando começa a unificar cadastro e encontra duplicidade que não fecha.

Miniatura do vídeo: Como usar user name (user id) na API oficial do WhatsApp Como usar user name (user id) na API oficial do WhatsAppCanal DATA7 · 5 min · assistir no YouTube
O identificador do usuário no payload do webhook, a troca do campo de destino no corpo do envio e a resposta chegando sem o telefone.

Onde o identificador aparece no payload

Ele aparece em mais de um lugar, e escolher o lugar errado é o segundo erro mais comum:

{
  "entry": [
    {
      "changes": [
        {
          "field": "messages",
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "5541999999999",
              "phone_number_id": "106540352242922"
            },
            "contacts": [
              {
                "profile": { "name": "Israel Henrique" },
                "user_id": "1a2b3c4d5e6f7g8h9i0j"
              }
            ],
            "messages": [
              {
                "from_user_id": "1a2b3c4d5e6f7g8h9i0j",
                "id": "wamid.HBgNNTUxMTk5OTk5OTk5ORUCABIYFjNFQjBDN...",
                "timestamp": "1759100000",
                "type": "text",
                "text": { "body": "Boa tarde, consegue me ajudar?" }
              }
            ]
          }
        }
      ]
    }
  ]
}

O valor que você usa para responder é o de dentro de messages. Ele identifica quem enviou aquela mensagem específica.

E há um motivo técnico forte para ler dali, e não do nível de cima: o objeto messages não existe no evento de status. Se o seu fluxo só sabe trabalhar quando encontra messages, ele quebra sozinho ao receber um status, em vez de responder a ele. Essa é a proteção mais simples contra o laço que multiplica mensagens, porque cada mensagem enviada gera novos eventos de status, que gerariam novas respostas, que gerariam novos status.

A regra é curta: responda mensagem, nunca status. Um envio bem-sucedido gera três eventos de status, sent, delivered e read, e um envio que falha gera um evento com o motivo. Nenhum dos quatro é uma mensagem de cliente.

Responder pelo user_id

Antes do envio, os seus identificadores. Se você só tem o token, comece por aqui:

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"
}

Com o phone_number_id em mãos, o envio pelo identificador do usuário é o corpo de sempre, com um campo trocado:

POST https://cloud.datafyapi.com.br/v1/106540352242922/messages
Authorization: Bearer sk_live_xxx
Content-Type: application/json

{
  "messaging_product": "whatsapp",
  "recipient": "1a2b3c4d5e6f7g8h9i0j",
  "type": "text",
  "text": { "body": "Respondendo a sua mensagem por aqui." }
}

É isso: no lugar de to, recipient. O resto do corpo continua idêntico ao de qualquer envio, inclusive nos outros tipos. Imagem, documento, áudio, botão e lista seguem a mesma estrutura, mudando só type e o objeto correspondente.

A resposta confirma o aceite, e nada além disso:

{
  "messaging_product": "whatsapp",
  "messages": [{ "id": "wamid.HBgNNTUxMTk5OTk5OTk5ORUCABEYEjBBRkZ..." }]
}

Uma dica de campo, porque é fácil errar montando isso numa ferramenta visual: passe o valor sem espaço em volta e sem as chaves de template que vêm da interpolação. Um espaço sobrando no fim do identificador é suficiente para o envio falhar.

Marcar como lida também funciona pelo identificador da mensagem

Quem atende por API costuma querer os dois tiques azuis no momento em que o atendente abre a conversa. Essa rota é simplificada e não pede o identificador do número:

POST https://cloud.datafyapi.com.br/messages/read
Authorization: Bearer sk_live_xxx
Content-Type: application/json

{
  "messaging_product": "whatsapp",
  "status": "read",
  "message_id": "wamid.HBgNNTUxMTk5OTk5OTk5ORUCABIYFjNFQjBDN..."
}

Repare que aqui o que importa é o wamid da mensagem recebida, não o identificador da pessoa. São chaves diferentes, e confundir as duas gera erro de recurso não encontrado.

Quando acontece o quê

Quando O que você recebe Como responder
O cliente manda a primeira mensagem contacts com o identificador, e messages com o conteúdo recipient com o valor de dentro de messages
O telefone ainda vem no payload Os dois caminhos funcionam Prefira o identificador e grave os dois
O telefone parou de vir Só o identificador O envio por to deixa de ser possível para aquele contato
A pessoa troca de número O identificador daquela relação segue o mesmo Nada muda no seu código
Chega um evento de status statuses, sem messages Não responda. Só registre
Passaram 24 horas sem mensagem dela Nada chega A resposta livre não sai mais. É template, e o recipient continua valendo

A última linha merece atenção: usar o identificador do usuário não muda a janela de atendimento. Quem abre e renova as 24 horas é a mensagem do cliente. Template enviado não abre janela. Fora da janela, a requisição pode voltar com HTTP 200 e um identificador de mensagem, e a falha chega depois no webhook de status. Isso vale igual para envio por telefone e por identificador.

E a cobrança também não muda: a Meta cobra por mensagem entregue, pela categoria e pelo país. No Brasil, a referência é de R$ 0,32 em marketing e R$ 0,035 em utilidade e autenticação. A partir de 1º de outubro de 2026, cada número passa a ter 1.000 mensagens de serviço gratuitas por mês, com cobrança a partir da milésima primeira.

Como guardar isso no seu banco

Três decisões resolvem o problema antes de ele existir:

Uma coluna para o identificador, desde já. Grave o user_id de cada contato na primeira mensagem, mesmo enquanto o telefone ainda chega. Migrar depois, sem histórico, significa esperar o cliente falar com você de novo para descobrir quem ele é.

O escopo junto da chave. Guarde o identificador sempre acompanhado do número ou da conta a que ele pertence, e faça a unicidade sobre o par. Assim o mesmo dado serve para várias conexões sem colidir.

O telefone como atributo, não como chave. Ele continua útil para relatório, conferência e cadastro, mas não pode ser aquilo de que o envio depende.

Vale ainda usar o cabeçalho x-datafy-delivery-id, que vem em toda entrega de webhook, como chave de idempotência do seu consumidor. Ele não substitui o dedup por mensagem, mas evita processar duas vezes a mesma entrega quando a sua aplicação demora a responder.

O que muda com a Datafy

Não muda: o nome de usuário, o ritmo da migração, o formato do payload e o campo recipient são todos da Meta. Nenhuma plataforma adia isso.

Muda o esforço de acompanhar a mudança. Como a API é um espelho da Cloud API, o campo novo chega no payload sem você atualizar versão de biblioteca ou de endpoint: o que a Meta manda é o que você recebe, sem alteração.

Muda a visibilidade. O log ao vivo do painel mostra o payload cru de cada mensagem que entra, o que é a forma mais rápida de ver se o telefone ainda vem no seu número ou se ele já sumiu. Como usar o log está aqui.

Muda a confiança no que chega. Os webhooks saem com assinatura HMAC nos cabeçalhos, o que importa quando o identificador do destinatário passa a vir só de fora.

Perguntas frequentes

O user_id é o mesmo em todas as empresas?

Não. Ele representa a relação entre a pessoa e cada empresa. A mesma pessoa tem um identificador com você e outro em qualquer outra conta, e não há como cruzar os dois.

Quando o telefone deixa de vir de vez?

A mudança é progressiva e não há data publicada. O final de 2026 aparece como expectativa do CTO da Datafy, e não como prazo da Meta. O certo é estar preparado antes.

Como envio mensagem usando o identificador?

Troque to por recipient no corpo e use o valor que veio dentro de messages. O resto do payload não muda, em nenhum tipo de mensagem.

Por que não usar o identificador que aparece no topo do payload?

Porque ler de dentro de messages é o que protege o seu fluxo: o objeto messages não existe no evento de status, então o fluxo quebra em vez de responder a uma notificação e criar um laço de mensagens.

A pessoa perde o identificador se trocar de número?

Não. Ela pode trocar de número e manter o mesmo nome de usuário, e a relação com a sua empresa continua a mesma. Essa estabilidade é justamente a vantagem para quem integra.

Isso muda a janela de 24 horas ou o preço?

Não muda nem uma coisa nem outra. Quem abre e renova a janela é a mensagem do cliente, template não abre janela, e a cobrança segue por mensagem entregue, por categoria e por país.

Eu já tenho um sistema que usa telefone como chave. Preciso reescrever tudo?

Não de uma vez. Comece gravando o identificador junto, em coluna nova, e passe o envio a preferir o recipient quando o valor existir. A troca fica pronta antes de ser obrigatória.

Como decidir

Se você está começando a integração agora, use o user_id como chave de contato desde a primeira mensagem, sempre acompanhado do número ou da conta a que ele pertence, e envie por recipient. Não há motivo para nascer com uma dívida técnica conhecida.

Se você já tem sistema rodando com telefone como chave, o caminho é incremental e não exige parada: crie a coluna, grave o identificador em toda mensagem que chega, faça o envio preferir recipient quando tiver o valor, e mantenha o telefone como atributo de conferência. Nenhuma dessas três etapas quebra o que já funciona.

Em qualquer um dos dois casos, garanta o filtro que separa mensagem de status no seu fluxo. Essa é a proteção que vale mais do que a migração em si. Como isso fica montado no n8n está aqui.

Responda uma mensagem pelo user_id

Chame GET https://cloud.datafyapi.com.br/me para pegar o phone_number_id, mande uma mensagem do seu celular para o número conectado, copie o identificador de dentro de messages na execução do webhook e responda com recipient no lugar de to.

Começar 7 dias grátis, sem cartão

Sem taxa de setup · Cancele quando quiser · Suporte por WhatsApp

Leia também

Continue por aqui