Um loop cego de retries costuma ser o motivo pelo qual uma integração com a API de terceiros, em vez de sobreviver a uma falha passageira, a agrava: continua batendo numa chave que já está errada, queima o limite de requisições em chamadas fadadas ao fracasso ou, pior ainda, cobra de novo pela mesma compra. A abordagem correta não começa pela pausa entre as tentativas, e sim pela classificação da causa: nem todo erro merece retry, e nem todo retry é seguro.
Três categorias de erros de API
Temporários: não têm relação com o conteúdo da requisição. Queda de rede, timeout de conexão, sobrecarga momentânea do serviço do provedor. A mesma requisição, com os mesmos parâmetros, funcionará normalmente depois de alguns segundos, porque o defeito estava no canal ou no momento, e não na requisição em si.
Permanentes: o caso oposto. Chave de acesso inválida, parâmetro inválido, falta de permissão para a operação. Essa chamada vai falhar igualzinho na primeira tentativa e na centésima, porque a causa está na própria requisição ou na configuração da conta. Repetir sem corrigir a causa não rende nada além de mais uma linha no log.
Financeiros: à primeira vista parecem temporários: saldo insuficiente na conta, nenhum número disponível para o país desejado. Uma nova requisição pode funcionar mais tarde, depois de uma recarga de saldo ou da atualização do estoque, mas repeti-la às cegas, ainda mais a própria operação de cobrança, não pode — as próximas seções explicam por quê.
O que repetir e o que não repetir
A regra é simples: só vale repetir o que pode se resolver sozinho com o passar do tempo. Falha de rede, timeout, resposta 5xx ou sinal de sobrecarga são candidatos a retry automático no esquema de backoff. Chave inválida, parâmetro incorreto, recusa por permissão: não faz sentido repetir enquanto a causa não for eliminada manualmente — é preciso ajustar a configuração e enviar a chamada de novo uma única vez, em vez de rodar um loop. A falta de saldo ou de estoque deve ser apresentada a quem fez a chamada como um estado à parte, e a decisão de repetir cabe à lógica de negócio ou ao usuário, não a um temporizador. Onde, no modelo de «compra pontual ou por período», a falta de estoque costuma aparecer com mais frequência é assunto do artigo Ativação OTP versus aluguel de número.
Backoff exponencial e o custo do retry cego
O backoff exponencial é uma pausa antes da próxima tentativa que cresce a cada vez: por exemplo, um segundo, depois dois, quatro, oito — até um teto de algumas tentativas, geralmente de três a cinco, depois do qual o ciclo é encerrado e a falha é repassada adiante como definitiva. Vale acrescentar à pausa uma pequena variação aleatória, para que muitos clientes que enfrentaram a mesma falha do provedor não o atinjam numa onda sincronizada justamente no momento da recuperação.
Sem classificação logo na entrada, o backoff não salva: aplicado a uma causa permanente, ele apenas estica no tempo chamadas inúteis, cada uma ocupando uma vaga no limite geral da conta. Enquanto o ciclo bate em vão numa chave inválida, as chamadas úteis da mesma conta — ativações reais, consultas de status — esbarram no mesmo limite e recebem recusa por limitação de taxa. Em automações com workers paralelos, como as descritas no artigo sobre cadastros via API, um único processo preso num ciclo de retries pode esgotar o limite de todos os outros.
Logs para a análise de incidentes
Depois de uma falha, a análise é feita pelo log, e não de memória; por isso é preciso registrar o suficiente para responder à pergunta «foi o provedor ou o nosso lado» sem reproduzir o problema de novo. O conjunto mínimo: horário da chamada, endpoint, identificador da requisição ou da ativação, código e texto da recusa do provedor, número da tentativa e parâmetros sem segredos — chaves e tokens não vão para o log.
Além da resposta do provedor, vale registrar também como o seu tratador classificou a causa: como temporária, permanente ou financeira. Se o classificador errou e uma causa permanente foi, na prática, repetida como temporária, isso só aparece nesse registro, e não apenas no código de resposta.
Idempotência de operações financeiras: como não cobrar duas vezes
O timeout não diz de forma inequívoca se a operação foi executada no servidor ou não: a conexão pode ter caído depois da cobrança, mas antes de a resposta chegar ao cliente. Repetir essa requisição sem proteção parece, para a API, uma nova operação — e leva a uma segunda cobrança pela mesma compra.
A chave de idempotência resolve o problema: o cliente gera um identificador único uma vez por operação e o envia em cada tentativa, inclusive nos retries após o timeout. O servidor memoriza o resultado devolvido para essa chave e, numa nova chamada com o mesmo valor, devolve esse resultado em vez de executar de novo. Essa é a única maneira segura de repetir uma chamada financeira — sem a chave, o risco de cobrança duplicada sempre existe.
Perguntas frequentes
É preciso fazer retry do erro 429 do mesmo jeito que de um timeout?
Sim, mas com uma pausa mais longa: o 429 significa não uma falha, e sim um limite de requisições esgotado, e um retry imediato só prolonga a espera para todos. Use o valor do cabeçalho da resposta, se o provedor o fornecer, ou comece o backoff já com uma pausa de alguns segundos, e não de um.
Posso repetir automaticamente uma requisição de cobrança de saldo em caso de timeout?
Não a requisição em si — apenas a operação com chave de idempotência. O timeout não diz se a operação foi executada no servidor antes de a conexão cair; repetir com a mesma chave é seguro, porque o provedor devolverá o resultado da operação já executada em vez de cobrar de novo. Sem a chave, esse retry corre o risco de duplicar o pagamento.
Quantas tentativas é razoável prever no retry de um erro temporário?
Em geral, de três a cinco tentativas com pausa exponencial e um teto total de espera de cerca de 30 a 60 segundos. Mais tentativas raramente mudam o resultado: se o provedor não se recuperou nesse intervalo, o problema é sistêmico, e o melhor é escalá-lo, e não continuar o ciclo.
Os códigos por categoria, o cabeçalho da chave de idempotência e os parâmetros de retry de cada endpoint estão na documentação da API. O recebimento de eventos por webhook, que também depende de retries e idempotência, é tratado no artigo webhooks: recebimento de códigos sem polling, e os cenários básicos de integração estão no material API de aluguel de números.