Ir para o conteúdo
Documentação Ir para o painel
A janela de 24 horas

A regra que decide se a sua mensagem chega

Ela não é da Zera, é da Meta, e é a causa mais comum de mensagem enviada que não aparece no celular de ninguém. Está antes do código de propósito: ler isto agora custa cinco minutos, e descobrir depois custa uma tarde depurando um código que estava certo.

A regra, em uma frase. Uma mensagem da pessoa para o seu número abre uma janela de 24 horas. Enquanto ela está aberta, você escreve o que quiser. Depois que ela fecha, a única coisa que passa é um modelo aprovado antes pela Meta.

Quem abre a janela é sempre a pessoa, nunca a empresa.

O que abre a janela

Nada desta seção é medido pelo produto da Zera. No plano da API o produto não guarda mensagem e não tem relógio de janela em lugar nenhum. O que está aqui é a regra da Meta, do jeito que ela está escrita na documentação que nós lemos. Onde a Zera mede alguma coisa, mais abaixo, a página diz que mede.

Abre a janela uma mensagem do cliente final para o seu número. Só isso. Quatro consequências que valem estar escritas:

  • Cada mensagem nova dela recomeça a contagem. Duas mensagens seguidas não viram 48 horas: a segunda apenas reinicia o relógio das 24.
  • O que você envia não abre janela e não estende a que está aberta. A janela é iniciada pelo usuário, e a contagem é da última mensagem que ele mandou.
  • A janela é da conversa, e não do seu número. Dez pessoas falando com você são dez relógios independentes, cada um no seu horário.
  • Não existe botão de reabrir. Fechou, o caminho é modelo aprovado, e só a resposta da pessoa reabre.

A outra janela, a de 72 horas

Existe um caso em que a janela nasce maior: quando a conversa começa por um ponto de entrada gratuito, que é o anúncio de clique para o WhatsApp e o botão de mensagem numa página do Facebook ou do Instagram. Nesse caso o acervo que nós lemos registra 72 horas, e não 24.

Isto a Zera não mediu. Está aqui porque saber que existe evita uma conclusão errada quando os seus números não baterem com as 24 horas. Não escreva código que dependa das 72 horas sem confirmar na documentação da Meta, e escreva para a Zera se você medir: a sua medição vira a nossa.

Com a janela aberta: mensagem livre, qualquer tipo

Livre quer dizer que o texto não precisa de aprovação prévia. Dentro da janela passam texto, imagem, áudio, documento, vídeo e localização, com o conteúdo que você escrever na hora. É o mesmo endereço de todo envio. Para o envio de modelo mudam duas coisas, e não uma: o type, que vira template, e o objeto do conteúdo, porque no lugar de text vai um objeto template com o nome do modelo, o idioma em language.code e as variáveis em components. Trocar só o type e manter o text não funciona.

Enviar uma mensagem livre
curl -X POST "https://graph.facebook.com/v25.0/SEU_PHONE_NUMBER_ID/messages" \
  -H "Authorization: Bearer SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "recipient_type": "individual",
    "to": "5511987654321",
    "type": "text",
    "text": {
      "preview_url": false,
      "body": "Oi Ana, o seu pedido saiu para entrega."
    }
  }'

As barras invertidas no fim das linhas são a continuação de linha do terminal do Linux e do macOS, e o comando roda igual no Git Bash e no WSL. No Windows PowerShell 5.1, que é o que vem instalado no Windows, ele não roda: lá curl é apelido de outro comando, e o corpo perde as aspas no caminho até o programa. No PowerShell 7 ele roda. A versão que serve nas duas está medida no passo 4 de O primeiro dia.

  • messaging_product é obrigatório, com janela aberta ou fechada. A documentação da Meta registra 400 para a chamada sem ele; a Zera não mediu esse envio, pela mesma razão que não imprime o código de erro da janela fechada mais abaixo.
  • to vai em formato internacional, sem o sinal de mais e sem pontuação. Um celular de São Paulo fica 5511987654321.
  • A resposta de sucesso traz "message_status": "accepted" e um wamid. Aceita pela Meta não é entregue no celular: entrega e leitura só aparecem no webhook, e o assunto é Receber mensagens.

O contrato completo desta chamada, campo por campo, e o corpo inteiro do envio de modelo estão em Referência.

Com a janela fechada: só modelo aprovado

Fora da janela, texto livre é recusado. O caminho é o mesmo endereço com "type": "template" e com o objeto template no lugar do text, citando um modelo que a Meta aprovou antes, no idioma exato daquele modelo. O corpo pronto para copiar está em Referência.

A regra de modelo não é repetida aqui de propósito. Como ver os seus, como criar um, as três categorias, os motivos de recusa e o que fazer com um modelo recusado estão em Modelos de mensagem, e essa é a página para onde você vai agora se a sua janela estiver fechada.

O erro que a Meta devolve fora da janela

O código exato ainda não foi medido do lado da Zera, e esta página não inventa um número.

As tabelas de erro que existem no nosso código são do fluxo de conexão do número, e não do envio de mensagem. A Zera nunca enviou uma mensagem com a credencial de um cliente para ver o que a Meta responde quando a janela está fechada. Um número escrito aqui de memória mandaria você procurar o erro errado.

O que dá para afirmar é a forma. A Meta devolve o erro dentro do corpo, e não só no status, e é este envelope que você precisa registrar inteiro:

O envelope de erro da Graph
{
  "error": {
    "message": "...",
    "type": "...",
    "code": O CÓDIGO QUE VOCÊ RECEBEU,
    "error_data": { "details": "..." },
    "fbtrace_id": "..."
  }
}

O error_data.details é texto livre e costuma ser a parte mais útil da resposta. O fbtrace_id é o que o suporte da Meta pede. Guarde os dois, junto com o code.

O que cada código quer dizer e qual é o próximo passo está em Erros. E se você bateu neste erro, escreva para [email protected] com o código e o fbtrace_id: esta seção ganha o número no dia em que alguém medir, e a sua tentativa é essa medição.

A categoria: o que a Zera mostra e o que ela não mostra

A Zera não expõe categoria de CONVERSA em lugar nenhum do painel. Se você procurou por isso e não achou, não estava escondido: não existe. O painel conhece outras duas categorias, e nenhuma delas é esta: a do modelo, na aba Modelos do número, e a de cobrança, na quebra de custo da aba Métricas, que diz quanto foi gasto em cada tipo de mensagem cobrável.

Cuidado para não ler esta lista como um menu de escolha. As categorias que você escolhe ao criar um modelo são três, e estão em Modelos de mensagem: UTILITY, MARKETING e AUTHENTICATION. A tela sabe traduzir cinco valores, porque ela mostra o que a Meta devolver na leitura, e a leitura de uma conta antiga ainda pode trazer OTP ou TRANSACTIONAL num modelo já existente. Os dois aparecem traduzidos como Código de verificação e Transacional, e não são opção de escolha hoje. Categoria fora dessas cinco aparece com o código cru, avisando que é valor novo, em vez de virar um rótulo inventado.

O que a categoria muda é o preço, e o preço não passa pela Zera. Quem cobra o envio é a Meta, direto de você. O painel mostra o custo aproximado que a própria Meta devolve, com a moeda dela ao lado e quebrado por categoria de cobrança, e nada além disso: o número que fecha a conta é o da fatura da Meta, nunca um gráfico de painel.

Duas coisas que nós lemos no acervo e não medimos ao vivo, marcadas para você conferir na fonte antes de usar numa planilha:

  • O preço do modelo varia por categoria, pelo país do número que recebe e, em utilidade e autenticação, por volume mensal.
  • Desde 1 de outubro de 2026, a Meta cobra por mensagem também a mensagem de serviço (a resposta livre dentro da janela aberta de 24 horas) e o modelo de utilidade enviado dentro dessa janela. A franquia é de 1.000 mensagens de serviço (resposta livre) grátis por mês, por número; acima disso, cada uma é cobrada. A utilidade não entra nessa franquia: é cobrada desde a primeira. Isso muda o preço, e não muda a regra de o que passa e o que não passa.

Para a sua contabilidade vale a tabela pública da Meta e a fatura dela, nunca uma tabela nossa.

As duas coisas de 24 horas que não são a mesma

Existe outro 24 horas no painel, e confundir os dois custa tempo. Um limita o que você escreve para uma pessoa; o outro limita com quantas pessoas diferentes você começa conversa por dia.

A janela de conversa comparada ao limite de mensagens do número
O que éO que ele limitaOnde você vê
A janela de conversa Se você pode escrever texto livre para uma pessoa agora. Em lugar nenhum do painel. Quem conta é o seu sistema.
O limite de mensagens do número Com quantas pessoas diferentes você pode iniciar conversa por dia. No painel, em Canais, na coluna Limite (Meta). Abrindo o número, na aba Detalhes, no cartão Estado na Meta, linha Limite de mensagens.

O limite do número é o campo messaging_limit_tier, que o cartão Estado na Meta, na aba Detalhes, lê da Meta. As faixas que a tela traduz são 50, 250, 1.000, 10.000 e 100.000 clientes por dia, mais a faixa sem limite de clientes por dia. Faixa fora dessas seis aparece com o código cru, do mesmo jeito que a categoria.

Um não substitui o outro. Você pode estar folgado no limite do número e mesmo assim não conseguir mandar texto livre, porque a janela daquela conversa fechou.

Como saber, do seu lado, se a janela está aberta

A resposta honesta é curta: quem sabe é o seu sistema. O painel da Zera não tem esse relógio, e não é esquecimento. O produto não guarda mensagem nenhuma no plano da API: não existe tabela de mensagem no banco e nenhuma rota lê a hora da última mensagem recebida. Um contador de janela no painel seria um número inventado.

E aqui as duas páginas se amarram: para contar as 24 horas você precisa saber a hora da última mensagem que chegou, e saber isso é receber os eventos. No plano da API, eles só chegam ao seu sistema depois de duas coisas: o endereço do seu servidor apontado na Meta, que o painel faz quando você salva o endereço com a conexão do número concluída, e o seu servidor respondendo à verificação da Meta. Leia Receber mensagens antes de escrever este pedaço, porque sem ele o resto desta seção não tem de onde tirar dado.

Com os eventos chegando, o relógio é seu, e ele cabe em cinco passos:

  1. Em toda mensagem recebida, guarde quem mandou e quando. Os dois campos estão no corpo que a Meta envia: messages[].from e messages[].timestamp, que chega como texto e em segundos, por exemplo "1755990000".
  2. Mantenha, por contato, só o timestamp mais recente. É o único valor que interessa: a janela é da última mensagem, e não da primeira.
  3. Antes de enviar texto livre, faça a conta na mesma unidade: agora menos o último timestamp daquele contato. O timestamp é texto em segundos e o relógio da maioria das linguagens está em milissegundos, então converta os dois lados antes de subtrair. Em JavaScript: Math.floor(Date.now() / 1000) - Number(ts) < 86400. Misturar as unidades não dá erro nenhum: a conta dá um número enorme, o seu sistema acha que toda janela está fechada e você paga modelo em conversa aberta. Abaixo de 24 horas, mensagem livre. Acima, modelo.
  4. Deixe uma folga na borda. O relógio do seu servidor e o da Meta não são o mesmo, e um envio que sai faltando dez segundos para fechar vira erro em produção. Tratar a janela como um pouco mais curta do que ela é sai mais barato do que o contrário.
  5. Trate a recusa como estado, e não como falha. Envio livre recusado naquela conversa quer dizer janela fechada: registre isso no seu lado e caia para modelo, em vez de tentar de novo o mesmo envio.

Se a sua mensagem não chegou, comece por aqui

  1. A pessoa mandou alguma mensagem para o seu número nas últimas 24 horas? Se não mandou, texto livre não passa, e o assunto é Modelos de mensagem.
  2. A resposta da Meta veio com accepted e um wamid? Então a janela não é o problema. Ela foi aceita, e o que falta saber é a entrega, que só aparece no webhook.
  3. Veio erro com corpo? Guarde code, message, error_data.details e fbtrace_id, e siga para Erros.
  4. O to está sem o sinal de mais e sem pontuação, com o 55 na frente?
  5. O messaging_product está no corpo? É o esquecimento mais comum de quem chegou copiando exemplo de outro fornecedor. A documentação da Meta registra 400 para a chamada sem ele, e a Zera não mediu.