Boas práticas do Verify
O Verify vem com padrões adequados para a maioria dos fluxos de código de verificação de uso único. Este guia cobre as decisões que os padrões não tomam por você: por quanto tempo um código deve ser válido, quantos dígitos ele precisa ter, qual canal é apropriado para o que você está de fato verificando e como distinguir um problema de entrega de um problema de verificação.
Quando um padrão público tem uma posição, este guia o cita. O padrão para autenticação por código de verificação é a NIST SP 800-63B, Digital Identity Guidelines: Authentication and Authenticator Management, consultada em 3 de setembro de 2026. As citações são da revisão atual. A Revisão 3 mais antiga, que muitos conselhos sobre OTP ainda citam, traz o próprio aviso da NIST: substituída pela SP 800-63-4 a partir de 1.º de agosto de 2025.
Mantenha o código com seis dígitos ou mais
Os códigos do Bird têm 6 dígitos por padrão e options.code_length aceita de 4 a 8 por solicitação (Configurações de verificação). O padrão é a escolha certa, e o limite inferior dessa faixa não é:
The verifier SHALL generate random authentication secrets that are at least six decimal digits (or equivalent) in length using an approved random bit generator
Um código de 4 ou 5 dígitos está dentro do que a API aceita e fora do que o padrão permite. Reduza o código apenas em um fluxo no qual você decidiu que a entropia do código de verificação não está fazendo o trabalho de segurança.
Mantenha a validade em dez minutos ou menos
Duration tem o padrão de 10 minutos e aceita de 1 a 999 (Configurações de verificação). O padrão fica exatamente no teto do padrão normativo:
In all cases, the authentication SHALL be considered invalid unless completed within 10 minutes.
Portanto, a faixa vai bem além do limite. Aumentar Duration para reduzir chamadas de suporte sobre códigos expirados é a única alteração de configuração que silenciosamente coloca um fluxo fora da 800-63B. Se os códigos estão expirando antes de os usuários conseguirem usá-los, a correção geralmente está no caminho de envio, não na janela de tempo.
Espere duas camadas de limitação de requisições
Uma tentativa de verificação é limitada duas vezes, e os dois limites respondem a ameaças diferentes.
Sua configuração. Maximum Retries tem o padrão de 5 e aceita de 1 a 10; além disso, a verificação falha com attempts_exhausted. O padrão normativo exige que esse limite exista para um código tão curto, e adiciona uma regra que vale conhecer:
Generating a new authentication secret SHALL NOT reset the failed authentication count.
O limite tem um teto, e este é o único ponto em que todo valor oferecido pelo Verify está confortavelmente dentro do padrão:
the verifier SHALL limit consecutive failed authentication attempts using a specific authenticator on a single subscriber account to no more than 100 by disabling that authenticator
Maximum Retries vai no máximo até 10, então nenhuma configuração que você escolha chega a 100. Isso é o espelho das duas seções acima: tamanho do código e duração têm cada um um valor suportado que sai da 800-63B, enquanto o limite de tentativas não tem nenhum.
Limites de plataforma do Bird, que se aplicam independentemente do que você configurar: 5 envios por endereço por hora corrida entre criação e reenvio, e 10 verificações por conjunto de endereço de destinatário por minuto. Ambos retornam 429 com um cabeçalho Retry-After (Proteções contra abuso). Eles existem para impedir que o tráfego de OTP seja usado contra a sua conta ou o aparelho de outra pessoa, então trate um 429 aqui como o sistema funcionando, e não como um limite a ser contornado.
Escolha o canal de acordo com o que você está verificando
O Verify entrega por e-mail, SMS, WhatsApp e Telegram (Canais). O padrão normativo trata dois deles de forma muito diferente, e a distinção diz respeito ao propósito do código, não ao canal que o transporta.
E-mail não é um fator de autenticação. A 800-63B é categórica:
Email SHALL NOT be used for out-of-band authentication because it may be vulnerable to:
- Access using only a password
- Interception in transit or at intermediate mail servers
- Rerouting attacks, such as those caused by Domain Name System (DNS) spoofing
A mesma passagem abre uma exceção para o caso ao qual o canal de e-mail do Verify se destina:
Confirmation codes that are sent to validate email addresses or are issued as recovery codes (see Sec. 4.2.1.2) are not authentication processes and not affected by the above prohibition.
Portanto, um código por e-mail que comprova que alguém controla um endereço está dentro da exceção do padrão e é válido. Um código por e-mail usado como segundo fator no login não está. Se o seu fluxo é o segundo caso, não use o canal de e-mail.
SMS e voz são permitidos, mas com restrições. A entrega pela rede telefônica traz três obrigações, em duas frases consecutivas:
Accordingly, verifiers SHALL ensure that alternative authenticator types are available to all subscribers and SHOULD remind subscribers of this limitation of PSTN out-of-band authenticators before binding one or more devices controlled by the subscriber. Verifiers SHOULD consider risk indicators (e.g., device swap, SIM change, number porting, other abnormal behavior) before using the PSTN to deliver an out-of-band authentication secret.
O SHALL é um requisito de produto, não uma configuração do Verify: se SMS é o seu único fator, você não o atende. A ordem de canais por país do Verify ajuda na entrega, porque WhatsApp é tentado primeiro na maioria dos países com SMS como fallback (Canais), mas SMS, WhatsApp e Telegram são todos caminhos de entrega para um único tipo de autenticador, out-of-band, então alternar entre eles não é oferecer um tipo alternativo. Os dois SHOULDs são aqueles que um time de produto implementa: um aviso no momento em que o usuário vincula um número de telefone, e uma verificação de sinais de portabilidade e troca de SIM antes de enviar para ele.
Leia a falha antes de reenviar
Um código que não chega e um código que chega e é digitado errado precisam de tratamentos diferentes, e os eventos os distinguem (Eventos).
verify.attempt.undelivered traz um reason, e o que acontece em seguida depende do plano de canais do destinatário. Em um destinatário com mais de um canal disponível, isso não encerra a verificação: Bird avança para o próximo canal, que recebe seu próprio verify.attempt.sent, então uma única tentativa não entregue não é uma verificação morta e não precisa de reenvio da sua parte. Em um destinatário com canal único, não há para onde avançar e a verificação termina.
Esse encerramento precisa de tratamento próprio, e um evento o identifica. O status failed é compartilhado: uma verificação chega a ele tanto quando códigos de verificação incorretos demais foram enviados, com reason attempts_exhausted, quanto quando nenhum canal planejado conseguiu entregar um, com reason undeliverable. Apenas o segundo emite verify.verification.failed. Portanto, em um destinatário com canal único, é esse evento, e não o status, que informa que ninguém recebeu um código.
Uma propriedade para projetar em torno dela em vez de descobrir depois, e esta é do próprio Bird, não do padrão normativo: Eventos afirma que os relatórios de entrega são indicativos, não garantidos, porque operadoras e provedores de e-mail variam no que confirmam e na velocidade com que o fazem. Em alguns mercados, um evento de tentativa chega com minutos de atraso ou não distingue entrega de aceitação. Construa o caminho de "I didn't get a code" sobre POST /v1/verify/verifications/next-channel, que avança a verificação, em vez de esperar por um evento de entrega que pode não vir.
Tente novamente a solicitação, não a verificação
Os três endpoints do Verify aceitam Idempotency-Key (Tentando novamente com segurança). Após um timeout ou uma conexão interrompida, tentar novamente com a mesma chave reproduz a resposta original: nenhum segundo código é enviado e nenhuma tentativa de verificação é consumida. Sem uma chave, uma nova tentativa após uma resposta perdida envia outro código e gasta mais um envio do limite por hora.
Saiba quanto custa um envio
A cobrança é associada a cada código enviado, pela tarifa do canal para o destino, e um reenvio ou fallback adiciona uma cobrança por envio (Custos e cobrança). Duas consequências moldam uma política de nova tentativa:
- Uma verificação que passa por vários canais custa vários envios, então um plano de canais amplo é uma decisão de custo tanto quanto de entrega.
- O Telegram cobra em um ponto diferente. O Telegram é consultado sobre se o número pode receber uma mensagem, e a cobrança é feita quando a resposta é sim, com uma tarifa fixa mundial. Um número que não pode ser alcançado é gratuito e avança para o próximo canal sem nada cobrado. Portanto, uma cobrança significa aceito para entrega, não entregue: um código que depois não é entregue continua cobrado, e a verificação paga novamente pelo canal para o qual avança. Onde essa segunda cobrança não é desejada, remova o Telegram da ordem de canais para esses países na página de Países (Custos e cobrança).
Próximos passos
- Enviando verificações: as configurações, as proteções e a lista completa de status
- Eventos: todos os eventos de sessão e entrega com seu payload
- Países: ordem e disponibilidade de canais por país
- Remetentes e identidade visual: a aparência de cada mensagem
Recursos relacionados
Continue com a documentação, guias e exemplos sobre este tópico.