---
title: "Vibecoding até o primeiro cliente: o que quebra fora da sua máquina"
description: "Webhook reentregue, status fora de ordem, janela fechando de madrugada e mídia que você não devia guardar. Seis defeitos com sintoma, causa e defesa."
url: "https://wame.api.br/blog/vibecoding-primeiro-cliente-o-que-quebra"
language: "pt-BR"
og:type: "article"
published_time: "2026-09-23"
modified_time: "2026-09-23"
author: "Raphael Serafim"
keywords: "vibecoding, webhook whatsapp, idempotencia webhook, janela de 24 horas whatsapp, api whatsapp, primeiro cliente saas"
reading_time: "9 min de leitura"
---

# Vibecoding até o primeiro cliente: o que quebra fora da sua máquina

> Webhook reentregue, status fora de ordem, janela fechando de madrugada e mídia que você não devia guardar. Seis defeitos com sintoma, causa e defesa.

Na sua máquina, tudo funciona. Você manda a mensagem, ela chega. O webhook dispara, a conversa aparece. Você testa por dez minutos, fecha o notebook e entrega para o primeiro cliente com a sensação, legítima, de que está pronto.

Na terça-feira ele liga dizendo que a mesma mensagem apareceu duas vezes. Na quinta, que o tique azul virou cinza. No domingo, que o sistema "parou de deixar responder" às quatro da manhã e voltou sozinho quando o cliente escreveu de novo. Nenhum desses três é bug no sentido comum: são comportamentos corretos de sistemas distribuídos encontrando um código que assumiu que o mundo é sequencial e acontece uma vez só. Aqui estão os seis mais frequentes, com sintoma, causa e a linha de defesa.

## 1. A mesma mensagem aparece duas vezes

**Sintoma.** A conversa mostra "Bom dia" duplicado, com o mesmo horário. Sempre em produção, nunca no teste. E aparece mais quando o sistema está lento, o que confunde o diagnóstico.

**Causa.** Todo provedor de webhook reentrega. Se o seu endpoint demorar a responder, se a conexão cair no meio, ou às vezes sem motivo aparente, o mesmo evento chega de novo. O seu código lê o corpo e faz `insert`, porque nos testes cada evento chegou exatamente uma vez.

**Defesa.** Índice único no identificador externo da mensagem — o id que o provedor manda, não um id seu. A reentrega colide com o índice e é descartada **em silêncio**, sem log de erro: não é uma falha, é o funcionamento esperado. Tratar como erro enche o log de ruído e esconde os problemas de verdade.

O detalhe que quase todo mundo erra: a deduplicação precisa vir antes de qualquer efeito colateral. Se você grava a mensagem, dispara uma notificação e depois deduplica, o cliente recebe duas notificações de uma mensagem só.

## 2. O tique azul vira cinza sozinho

**Sintoma.** O atendente vê a mensagem como lida, atualiza a tela e ela voltou para "entregue". Ou nunca sai de "enviada", mesmo com o cliente tendo respondido.

**Causa.** Os recibos de entrega não chegam na ordem em que aconteceram. `read` pode chegar antes de `delivered`, e o seu código faz `status = evento.status`, escrevendo por cima.

**Defesa.** Status não é um valor, é uma escada que só sobe: `enviada → entregue → lida`. Cada recibo compara antes de gravar, e recibo mais atrasado que o estado atual é ignorado. A exceção é `falha`, que é terminal e pode chegar de qualquer estado — quando a mensagem falha, ela falhou, independentemente do que chegou antes.

Duas armadilhas menores na mesma família. Recibo de entrega só se aplica a mensagem que **saiu** do seu sistema; mensagem recebida já nasce entregue, e tentar aplicar recibo nela cria estado impossível. E se você guarda "quando foi a primeira vez" para alguma métrica, grave com uma operação que só aceita valor menor, nunca sobrescrevendo — senão um recibo atrasado reescreve o passado.

## 3. O sistema "não deixa responder" de madrugada

**Sintoma.** O atendente chega às oito da manhã, abre uma conversa de ontem e a caixa de digitação está bloqueada, ou o envio é recusado com um erro que fala de template. Uma hora depois o cliente escreve e tudo volta ao normal.

**Causa.** A janela de 24 horas. Depois que o cliente manda uma mensagem, você tem 24 horas para responder com texto livre. Passado o prazo, iniciar conversa exige um template aprovado pela Meta. A janela fecha pelo relógio, então ela fecha de madrugada, num horário em que ninguém está olhando.

**Defesa.** Três partes, e nenhuma é opcional.

Primeiro, a conversa guarda a data em que a janela expira, atualizada a cada mensagem **recebida**. Segundo, a tela lê esse campo e mostra a lista de templates no lugar da caixa de digitação quando a janela fechou — com uma frase dizendo por quê, senão o atendente conclui que o sistema quebrou. Terceiro, o envio valida no servidor de qualquer jeito: a tela é conveniência, e um `curl` ou uma aba antiga passariam por cima dela.

O mecanismo completo de template — como criar, o que a Meta recusa e por quê — está em [Templates do WhatsApp pela API](/blog/templates-whatsapp-api-criar-aprovar-enviar). Vale ler antes de desenhar a tela de conversa, não depois.

## 4. As mensagens chegam na ordem errada

**Sintoma.** O bot manda um áudio e um menu de opções. No celular do cliente, o menu aparece primeiro e o áudio depois — a conversa fica sem sentido e parece que alguém programou errado.

**Causa.** Mídia enviada por URL só é entregue depois que a plataforma **baixa o arquivo**. Texto sai na hora. Se você dispara os dois em sequência imediata, o texto ultrapassa a mídia.

**Defesa.** Espaçar os envios automáticos, com um respiro maior depois de mídia do que depois de texto. Isso reduz a inversão a quase zero, mas é honesto dizer que **não a elimina**: garantia mesmo exigiria esperar o recibo de envio de cada mensagem antes de mandar a seguinte, prendendo o seu fluxo a um evento que pode demorar ou não chegar.

Na prática, o respiro resolve o caso real e o custo é conversas um pouco mais lentas — que por acaso também parecem mais naturais. Vale deixar o intervalo configurável, para conseguir desligá-lo em scripts de manutenção.

## 5. O número perde qualidade, e depois perde o limite

**Sintoma.** Os envios começam a falhar depois de um certo volume diário, sem que nada no seu código tenha mudado. Ou a taxa de entrega cai e ninguém entende por quê.

**Causa.** A Meta atribui uma nota de qualidade ao número, derivada de bloqueios e denúncias de quem recebe, e essa nota governa quantas conversas você pode iniciar por dia. Disparo para lista comprada, mensagem sem contexto e template que parece propaganda derrubam a nota rápido.

**Defesa.** Três hábitos, e o primeiro é o que mais importa: **só mande para quem pediu**. Opt-in registrado, com data e origem, e opt-out que funcione de verdade — se alguém escreve "para", pare, e pare no mesmo minuto.

Os outros dois: acompanhe a nota em vez de descobri-la pela recusa, e não use o mesmo número para prospecção fria e para atendimento. O funcionamento do Tier e da nota está em [Quality Rating e limite de mensagens](/blog/quality-rating-limite-mensagens-whatsapp), com os números atuais.

Vale dimensionar o risco: número bloqueado não é uma inconveniência, é o canal de vendas do seu cliente desligado, e a conversa que vem em seguida é com você.

## 6. Você está guardando mídia que não devia

**Sintoma.** Nenhum, por meses. Depois o disco enche, ou o cliente pede o contrato de tratamento de dados e alguém pergunta onde estão os arquivos que os clientes dele mandaram.

**Causa.** É a implementação óbvia. O webhook avisa que chegou uma imagem, você baixa, salva em disco ou num bucket, guarda o caminho no banco. Funciona de primeira, e cada foto de documento, comprovante e receita médica que passou pelo atendimento fica lá.

**Defesa.** Não guarde. Faça proxy: a tela pede o arquivo ao seu servidor, o servidor valida a sessão e busca o conteúdo na API de mensageria no momento do pedido. Zero disco, zero bucket, zero backup de arquivo — e, quando alguém perguntar o que você armazena, a resposta é "metadado e texto".

Isso tem um custo real, e vale dizer: cada visualização é uma ida à rede, e mídia muito antiga pode não estar mais disponível do lado de lá. Para atendimento, é uma troca que quase sempre compensa. Se o seu produto precisa de arquivo permanente — um contrato assinado, por exemplo —, aí é uma decisão consciente, com retenção definida e escrita no contrato. O que não pode é acontecer por acidente.

## O que esses seis têm em comum

Olhando junto, dá para ver o padrão, e o padrão é mais útil que a lista.

Nenhum deles aparece em teste feliz. Todos aparecem só com **tempo** e **volume** — duas coisas que não existem na sua máquina. E os seis vêm da mesma suposição implícita: a de que o mundo lá fora é como o seu ambiente de desenvolvimento, onde as coisas acontecem uma vez, na ordem, imediatamente e sem consequência jurídica.

A defesa geral, antes das específicas, é escrever três testes desconfortáveis assim que a integração funcionar: um que manda o mesmo webhook duas vezes, um que entrega os recibos de status na ordem inversa e um que tenta enviar com a janela vencida. São dez minutos de trabalho e eles encontram, de uma vez, metade desta lista.

O [dicionário de erros da API do WhatsApp](/blog/erros-api-whatsapp-como-tratar) ajuda na hora em que o código devolver um número que você não reconhece — que é como a maioria dessas coisas se apresenta na primeira vez.

## Conclusão

Nada aqui é sobre a qualidade do código que a IA escreveu para você. O código está certo para o mundo que foi descrito a ela, e o mundo que foi descrito a ela é o seu ambiente de desenvolvimento.

O que separa um protótipo de um sistema em uso não é elegância nem cobertura de teste. São seis suposições sobre o mundo: que o evento chega uma vez, na ordem, que o prazo não fecha sozinho, que a nota do número não cai, e que guardar arquivo é gratuito. Corrija as seis e o resto do seu sistema aguenta bem mais tráfego do que você imagina.

Se você ainda está montando o CRM, [as três partes que a IA não resolve](/blog/criar-crm-com-ia-o-que-a-ia-nao-resolve) cobre o que vem antes desta lista. Se o plano é vender, [o que falta no protótipo para virar produto](/blog/de-prototipo-a-produto-vender-o-crm-que-voce-criou) cobre o que vem depois.

## Perguntas frequentes

### Por que o webhook chega duas vezes se eu respondo 200?

Porque o provedor reentrega quando não recebe a confirmação no prazo dele, e a sua resposta pode ter demorado, se perdido na rede ou chegado tarde por um segundo. Responder `200` antes de processar reduz muito a frequência, mas a única defesa confiável é a idempotência por identificador externo.

### Como eu sei se a janela de 24 horas está aberta numa conversa?

Guardando, na própria conversa, a data de expiração — atualizada toda vez que o cliente manda uma mensagem. Não dá para deduzir isso na hora do envio sem consultar o histórico, e não dá para confiar na memória do atendente: a janela fecha pelo relógio, muitas vezes de madrugada.

### Preciso me preocupar com qualidade do número se mando pouca mensagem?

Volume baixo ajuda, mas a nota vem de bloqueios e denúncias, não de quantidade. Cem mensagens não solicitadas fazem mais estrago que mil mensagens pedidas — e como o limite diário depende dessa nota, o problema aparece exatamente no dia em que o seu cliente mais precisa mandar.

### Guardar mídia de conversa é problema de LGPD?

É um risco que você assume, e frequentemente sem perceber que assumiu. No atendimento passam documentos, comprovantes e informação de saúde; guardá-los significa responder por eles no contrato, no backup e na exclusão a pedido. Fazer proxy sob autenticação evita a maior parte disso sem tirar nada do usuário.

### Esses problemas somem se eu usar uma API gerenciada?

Alguns somem, outros não. A conexão com a Meta, o token e o formato de webhook deixam de ser seus; a reentrega, a ordem dos recibos e a janela de 24 horas continuam sendo — elas são da natureza do canal, não do fornecedor. Qualquer um que prometa o contrário está descrevendo um sistema que você não vai reconhecer em produção.
