Como reduzir o custo do SMS de verificação com fallback inteligente
Guia prático para cortar o custo do SMS de verificação: WhatsApp como primeiro canal, SMS como fallback, defesas contra fraude e métricas de custo por verificação.
O custo do SMS de verificação costuma ser invisível no começo: algumas dezenas de códigos por dia, uma fatura pequena, nada que apareça na reunião de produto. Aí o cadastro cresce, o botão "reenviar código" vira o mais clicado do app, alguém descobre que dá para lucrar disparando seus SMS para números premium — e a verificação de telefone passa a disputar espaço com a infraestrutura no orçamento.
A boa notícia é que a maior parte desse gasto não vem de usuários legítimos verificando o número uma vez. Vem de reenvios, de números inválidos, de fraude e de usar o canal mais caro como primeira opção. Cada uma dessas fontes tem uma correção conhecida.
Este guia mostra onde o custo nasce, como colocar o WhatsApp na frente do SMS, como lidar com números sem WhatsApp, como barrar SMS pumping e reenvios abusivos e como medir e simular o custo por verificação.
Onde nasce o custo do SMS de verificação
O SMS corporativo (A2P) é cobrado por mensagem, com preço que varia por operadora e país. A regra mais importante para entender a fatura é esta: em geral, o SMS é cobrado quando o provedor aceita a mensagem, não quando ela é entregue. Um código enviado para um número fixo, desativado ou digitado errado custa o mesmo que um código entregue.
A partir daí, o volume de envios se decompõe em cinco parcelas:
- Verificações legítimas: uma mensagem por usuário que conclui o fluxo. É o único custo que você quer pagar.
- Reenvios: o usuário não recebeu (ou não esperou) e clicou de novo. Sem cooldown, uma verificação vira duas ou três mensagens.
- Abandono: o código foi entregue, mas o usuário não voltou para digitá-lo.
- Números inválidos: telefones fixos, DDDs inexistentes e erros de digitação que passaram sem validação de formato.
- Fraude: disparos automatizados contra o seu formulário para gerar tráfego a números de alta tarifa (SMS pumping).
Há ainda um detalhe técnico que multiplica tudo: um SMS tem 160 caracteres no alfabeto GSM-7 e apenas 70 quando contém caracteres fora dele, como emojis. Textos maiores são quebrados em partes, e cada parte é cobrada como uma mensagem. Quem monta o próprio canal — por exemplo, seguindo o guia para enviar SMS com PHP do APIBrasil Blog — precisa manter o texto do código curto, senão paga dois SMS por código.
WhatsApp primeiro, SMS como fallback
A mudança de maior impacto é trocar a ordem dos canais. O WhatsApp está na maior parte dos celulares brasileiros, entrega em segundos, confirma leitura e, no modelo de cobrança da aut2fa, só é cobrado na entrega ou na leitura: uma mensagem que não chega não gera custo. O SMS continua existindo, mas como segunda opção, para quem não tem WhatsApp naquele número.
Com uma API multicanal, isso não é código, é configuração. Na aut2fa, os canais permitidos ficam na aplicação (no painel), e a plataforma tenta os canais do mais barato ao mais caro. Se o WhatsApp aceita a mensagem mas não confirma a entrega em 30 segundos, o envio passa para o próximo canal. Do lado do seu backend, continua existindo uma única chamada:
curl https://api.aut2fa.com/v1/send \
-H "Authorization: Bearer $AUT2FA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cadastro-7f3a1c" \
-d '{"to":"+5531987654321","locale":"pt-BR"}'
A resposta 202 traz o id do envio (snd_...) e o expires_at do código. O canal usado aparece depois, no campo channel do GET /v1/send/{id}/status ou nos webhooks.
Quem prefere orquestrar os canais por conta própria pode partir do tutorial de como enviar SMS e WhatsApp pelo backend do Programador Brasil. Só não subestime o trabalho escondido — timeout de entrega, deduplicação de reenvios e estado de cada código — que separa um fallback de "mandar nos dois canais e pagar duas vezes".
Como detectar números sem WhatsApp
Não existe uma consulta barata e confiável que diga, antes do envio, se um número tem WhatsApp ativo. A abordagem prática tem três camadas, e nenhuma delas custa uma mensagem extra.
1. Validar o formato antes de enviar
Boa parte dos números "sem WhatsApp" nem são celulares. No Brasil, o celular tem DDD de dois dígitos e nove dígitos começando em 9. Normalize para o formato internacional e rejeite o resto antes de chamar a API:
// Normaliza para E.164 e aceita apenas celulares brasileiros
function normalizarCelularBR(entrada) {
const digitos = entrada.replace(/\D/g, "").replace(/^55/, "");
if (!/^[1-9]{2}9\d{8}$/.test(digitos)) return null; // DDD + 9 dígitos iniciados em 9
return `+55${digitos}`;
}
2. Deixar o fallback descobrir
Para números válidos, a resposta mais barata é tentar o WhatsApp e cair para o SMS no timeout. É o que a plataforma faz sozinha; você não decide nada no momento do envio.
3. Guardar a memória de canal
Registre, por número, qual canal acabou sendo usado. No webhook, cada aceitação gera um evento send.sent cujo data.channel informa o canal; no fallback, chega um segundo send.sent com o canal novo. Um handler mínimo em Node.js:
app.post("/webhooks/aut2fa", express.json(), async (req, res) => {
// Compare o token privado configurado no painel antes de confiar no corpo
if (req.get("Aut2fa-Token") !== process.env.AUT2FA_WEBHOOK_TOKEN) {
return res.sendStatus(401);
}
const { type, data } = req.body;
if (type === "send.sent") {
// Cada canal que aceita a mensagem gera um send.sent; no fallback, o último vence
await db.canalPorNumero.upsert(data.to, { canal: data.channel, em: new Date() });
}
res.sendStatus(200); // 2xx encerra as retentativas do webhook
});
Essa memória mostra o mix real de canais da sua base e permite sugerir o canal certo quando o produto deixa o usuário escolher. Como cada aplicação tem seu próprio conjunto de canais, dá para manter uma aplicação "WhatsApp com fallback" e outra "só SMS" para quem informou que não usa WhatsApp.
Bloquear SMS pumping e reenvios em excesso
SMS pumping é o golpe em que um atacante usa o seu formulário de verificação para disparar milhares de códigos a números de alta tarifa, geralmente internacionais, e divide a receita com quem controla essas faixas. Para você, aparece como um pico de envios sem verificação concluída. O artigo sobre o que é SMS pumping e como se proteger entra em detalhes; aqui ficam as defesas que mais reduzem custo:
- Lista de países permitidos: se você só atende o Brasil, recuse qualquer
toque não comece com+55antes de chamar a API. - Limite por destinatário: a aut2fa permite limitar envios por destinatário por hora na aplicação (o valor inicial é 5). Um usuário legítimo nunca precisa de mais.
- Limite por aplicação por minuto: também configurável no painel, funciona como disjuntor contra rajadas.
- Limite por IP e por dispositivo no seu backend: o atacante troca de número, não de origem.
- Exigir tentativa de verificação antes do próximo envio: quem pede três códigos sem digitar nenhum não é usuário.
Os reenvios legítimos precisam de regra também: cooldown de 30 a 60 segundos no botão, no máximo dois ou três reenvios por sessão e, quando a API devolver HTTP 429, o tempo do cabeçalho Retry-After na tela em vez de um botão que o usuário martela. Para que um clique duplo não vire dois envios cobrados, mande sempre o mesmo Idempotency-Key na retentativa.
Parte dos reenvios acontece porque o usuário esperava um SMS e não viu o código chegar no WhatsApp. Dizer na tela "enviamos um código pelo WhatsApp para +55 31 9****-4321" corta esse ruído.
Como medir o custo por verificação
A métrica que importa não é o preço por mensagem, e sim o custo por verificação concluída: o gasto do período dividido pelo número de códigos que voltaram com valid: true. Ela captura reenvios, abandono, fraude e mix de canais em um único número — é o custo do SMS de verificação que o seu produto paga de fato.
Quatro indicadores de apoio explicam as variações:
| Indicador | Como calcular | O que revela |
|---|---|---|
| Taxa de conversão | verificados ÷ enviados | Abandono, entrega ruim, fraude |
| Reenvios por verificação | envios ÷ usuários únicos | Cooldown fraco, UX confusa |
| Mix de canais | envios por channel ÷ total | Quanto ainda cai no SMS |
| Taxa de falha | status = failed ÷ enviados | Números inválidos, failure_reason |
Com os eventos dos webhooks gravados em uma tabela, a consulta é simples:
SELECT channel,
COUNT(*) AS envios,
SUM(CASE WHEN verified_at IS NOT NULL THEN 1 ELSE 0 END) AS verificados
FROM envios_otp
WHERE created_at >= NOW() - INTERVAL '7 days'
GROUP BY channel;
Acompanhe por semana: queda na conversão com alta nos envios é sinal de pumping; alta no mix de SMS após mudar o formulário indica validação de formato quebrada.
A mesma conta vale fora do cadastro. Equipes de suporte que precisam confirmar a identidade do cliente no atendimento antes de alterar dados também disparam códigos, e esse volume entra na fatura. Se o atendimento já acontece pelo WhatsApp, enviar o código pelo mesmo canal é a opção mais barata e a mais natural para o cliente.
Planilha de simulação: quanto você economiza
Para estimar o impacto antes de mudar, monte uma planilha com seis entradas. Os preços por canal você pega na página de preços ou na sua tabela atual; o restante sai das métricas da seção anterior.
| Célula | Entrada | De onde vem |
|---|---|---|
| V | Verificações concluídas por mês | Banco de dados |
| p | Fração de números entregues por WhatsApp | Memória de canal |
| C_wa | Preço de uma mensagem WhatsApp entregue | Tabela do provedor |
| C_sms | Preço de um SMS aceito | Tabela do provedor |
| r | Reenvios médios por verificação | envios ÷ verificados − 1 |
| f | Fração de envios inválidos ou fraudulentos | status failed + bloqueios |
O custo mensal estimado fica:
Custo = V × (1 + r) × [ p × C_wa + (1 − p) × C_sms ] × (1 + f)
Simule três cenários: o atual (p = 0, r e f medidos), "WhatsApp primeiro" (p medido, r e f iguais) e o completo (r e f reduzidos pelas regras de reenvio e bloqueio). A diferença entre o primeiro e o último é o que o fallback inteligente vale por mês — com números seus, defensáveis em qualquer reunião.
Perguntas frequentes
O WhatsApp sempre sai mais barato que o SMS?
Depende da tarifa de cada canal no seu provedor, então confira a tabela de preços antes de assumir. O que torna o WhatsApp vantajoso na maior parte dos casos é a cobrança só na entrega ou leitura, somada a uma entrega mais confiável. A comparação detalhada está em SMS ou WhatsApp para código de verificação.
E se o usuário não tiver WhatsApp no número informado?
O fallback resolve: o WhatsApp não confirma a entrega dentro do tempo limite e o envio passa para o SMS, sem nova chamada do seu backend. Na interface, informe o canal usado e libere o reenvio só depois do cooldown.
Posso mandar o código por e-mail para cortar custo?
Pode, e o e-mail é o canal mais barato quando o objetivo é confirmar um endereço de e-mail. Ele não prova a posse do telefone, então use-o em login ou recuperação de conta, não na verificação de número.
Como sei se estou sofrendo SMS pumping?
Os sinais clássicos são picos de envio fora do horário normal, números sequenciais ou de um mesmo prefixo, DDIs de países que você não atende e taxa de verificação próxima de zero nesse grupo. Limite por destinatário, lista de países e limite por IP cortam a maior parte do problema.
Próximos passos
Comece pela medição: uma semana de dados já mostra qual parcela pesa mais. Depois, ative o WhatsApp como primeiro canal, ligue os limites por destinatário e por aplicação e aplique as regras de reenvio no front.
Para experimentar sem gastar, crie uma aplicação em modo de teste no painel da aut2fa: o código é sempre 000000, nenhuma mensagem é entregue e nada sai do saldo. Novas contas ainda recebem 10 envios reais gratuitos para validar a entrega em produção antes da primeira recarga.