Convide e ganhe

Como funcionam as recompensas

Compartilhe seu link. Quando um amigo se cadastrar por ele e adicionar saldo, você receberá a recompensa exibida nas recargas posteriores.

Limites do OpenRouter e Erro HTTP 429: Como Diagnosticar e Recuperar

Um guia prático para diagnosticar os erros HTTP 429 e 402 no OpenRouter: como diferenciar cotas do plano gratuito, limites da plataforma e restrições de provedores upstream, inspecionar headers e metadados, além de um script em Python para repetição resiliente de requisições.

Conteúdo
Limites do OpenRouter e Erro HTTP 429: Como Diagnosticar e Recuperar

Ao enviar grandes volumes de requisições para modelos de IA por meio do gateway OpenRouter, aplicações cliente frequentemente se deparam com o código de status HTTP 429 Too Many Requests. Como o OpenRouter agrega dezenas de provedores de inferência independentes, esse erro pode ter origem em camadas completamente distintas da infraestrutura. Uma repetição imediata e ingênua geralmente resulta no bloqueio da taxa do cliente ou no desperdício de tentativas de recuperação. Para restabelecer um fluxo estável de requisições, é essencial identificar o nível exato da falha e adotar a correção correspondente: aguardar um período de espera, reduzir o paralelismo, alternar provedores de modelos ou ajustar limites de gastos.

Camadas de Limitações: Plano Gratuito, Plataforma e Upstream

A documentação oficial OpenRouter Limits diferencia limites de taxa de serviço, taxa de transferência de provedores individuais e aplicação de restrições por saldo de conta.

Na página OpenRouter Pricing, a tabela base do plano gratuito estabelece um teto de 50 requisições por dia para modelos gratuitos disponíveis publicamente (com o sufixo :free). Como os limites exatos de requisições por minuto (RPM) e os limites de cada nível podem mudar ao longo do tempo, os valores numéricos vigentes devem sempre ser verificados na tabela de limites atualizada.

Ao diagnosticar falhas, é fundamental separar as camadas responsáveis pelo código HTTP 429 e pelo status correlato HTTP 402:

  1. Limites de taxa da plataforma OpenRouter. Ocorrem quando o próprio roteador recebe requisições com frequência excessiva. A cota diária do pool gratuito pertence a essa categoria de limitações da plataforma (e não a uma restrição independente de terceiros): ao ultrapassar o limite de 50 requisições diárias em modelos gratuitos, a plataforma rejeita as requisições recebidas até que o contador diário seja reiniciado. Quando um limite de taxa da plataforma é acionado, o servidor retorna os headers HTTP X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset. Respostas bem-sucedidas (HTTP 200) não contêm esses headers operacionais, o que significa que as aplicações cliente não podem depender deles durante o tráfego normal e sem erros para antecipar limites.
  2. Limites de taxa do provedor upstream (upstream rate limit). Os modelos ficam fisicamente hospedados e em execução na infraestrutura de empresas específicas (como Anthropic, Meta, DeepSeek, Mistral ou serviços terceirizados de nuvem). Se a infraestrutura desse parceiro upstream estiver sobrecarregada, o OpenRouter repassa o status 429 diretamente ao cliente. Na estrutura do corpo da resposta, o campo error.metadata.provider_code contém o código de erro bruto do provedor upstream quando disponível (por exemplo, 429), e não o nome ou identificador textual do provedor.
  3. Restrições financeiras (HTTP 402 Payment Required). A documentação OpenRouter Limits distingue explicitamente o esgotamento financeiro dos limites de frequência. O status 402 indica saldo insuficiente ou negativo na conta da organização, ou que o teto de gastos de uma chave de API individual (key cap) foi atingido, em vez de representar estritamente um saldo nulo.

Os parâmetros vigentes de uma chave podem ser inspecionados por meio de uma requisição direta à API:

curl -s -X GET https://openrouter.ai/api/v1/key \
  -H "Authorization: Bearer $OPENROUTER_API_KEY"

O payload de resposta retorna os campos usage, limit_reset e limit_remaining. Um valor limit_remaining: null indica que nenhum teto local de gastos está configurado para essa chave de API específica. Esse valor não comprova a existência de créditos no saldo principal da organização; apenas confirma a ausência de um limite artificial de gastos imposto a esse token individual.

Tabela de Diagnóstico Resumida

Código de resposta e sinaisFonte de inspeçãoCausa raizAção do cliente
HTTP 402 Payment RequiredEndpoint GET /api/v1/key ou painelSaldo insuficiente ou negativo da organização ou teto da chave atingido (limit_remaining: 0)Recarregar saldo ou aumentar a cota da chave; repetições automáticas sem alterações são inúteis
HTTP 429 com headers X-RateLimit-*Headers HTTP da resposta do gatewayLimite de concorrência ou frequência da própria plataforma OpenRouter excedidoInspecionar o header Retry-After e reduzir o número de threads concorrentes
HTTP 429 com código em provider_codeCampo JSON error.metadata.provider_code (opcional)Sobrecarga ou indisponibilidade do provedor upstream (código de erro bruto do upstream)Alternar modelos ou provedores pode ajudar, mas não garante a recuperação; atribuir provedor específico em Activity > provider_responses
HTTP 429 em modelos :freeSeção OpenRouter PricingLimite diário da plataforma esgotado (50 requisições/dia) ou capacidade total indisponívelMigrar para um modelo pago ou adiar a execução
HTTP 429 com roteamento complexoPainel: Activity > Requisição > View Raw MetadataFalha intermediária em nós dentro do objeto provider_responsesIdentificar o provedor com falha e verificar a cadeia de fallback no guia de BYOK/Roteamento

Análise de Dois Cenários: Limite de Chave vs. Falha de Provedor

O modo como uma aplicação cliente reage à interrupção das requisições fundamenta-se na inspeção de metadados. Abaixo apresentamos dois cenários hipotéticos (exemplos ilustrativos, e não observações de uma conta real).

Cenário 1 (Hipotético): Esgotamento do Limite Local do Token

Neste cenário hipotético, um processo em segundo plano recebe uma rejeição HTTP 402. A existência de saldo positivo na conta da organização é uma premissa inicial explícita neste exemplo, verificada separadamente pelo painel de controle (a resposta do endpoint da chave em si não confirma o saldo global da organização). Uma consulta ao endpoint https://openrouter.ai/api/v1/key retorna:

{
  "data": {
    "label": "worker-key",
    "usage": 25.04,
    "limit": 25.0,
    "is_free_tier": false,
    "limit_remaining": 0.0,
    "limit_reset": null
  }
}

Embora o saldo principal da conta seja positivo por premissa, o campo limit_remaining chegou a zero. O token atingiu o teto de gastos de 25 dólares definido pelo administrador. Quaisquer tentativas automáticas de repetição utilizando essa mesma chave falharão com o mesmo erro 402. O processo de trabalho deve ser encerrado imediatamente, notificando o administrador para que o teto do token seja ajustado.

Cenário 2 (Hipotético): Sobrecarga do Provedor Upstream

Como exemplo ilustrativo, considere o caso em que uma requisição retorna HTTP 429 devido a uma falha no lado do upstream. O simples recebimento do código 429 não fornece dados suficientes para concluir sobre a integridade geral do gateway ou a presença de saldo na conta. No corpo do erro, pode existir um bloco opcional de metadados:

{
  "error": {
    "message": "Provider returned rate limit error",
    "code": 429,
    "metadata": {
      "provider_code": 429
    }
  }
}

O campo error.metadata.provider_code é opcional e traz o código de status bruto retornado pelo provedor upstream quando disponível (neste exemplo, 429), e não o nome ou identificador textual da empresa provedora. A presença desse código isoladamente não identifica qual provedor específico rejeitou a chamada.

Para identificar o provedor causador da falha, acesse no console de gerenciamento: Activity > requisição específica > View Raw Metadata. O objeto provider_responses lista cada um dos hosts consultados e seus respectivos status de retorno, conforme documentado no guia de roteamento. Alternar para outro provedor ou alterar o modelo de destino pode ajudar na resolução, mas não garante a recuperação imediata.

Script de Repetição de Requisições para Cliente em Python 3

Quando o status HTTP 429 é de natureza temporária, o tempo de espera antes da próxima tentativa é calculado a partir do header Retry-After. O servidor fornece esse header na forma de um número inteiro de segundos ou como uma data formatada no padrão HTTP.

A implementação abaixo utiliza exclusivamente a biblioteca padrão do Python 3. Ela trata unicamente erros 429, aplica recuo exponencial com jitter aleatório caso a orientação do servidor não esteja presente e interrompe a execução se o servidor exigir uma espera superior a 60 segundos.

import email.utils
import json
import os
import random
import sys
import time
import urllib.error
import urllib.request

API_KEY = os.environ.get("OPENROUTER_API_KEY")
MODEL_ID = os.environ.get("OPENROUTER_MODEL_ID", "openai/gpt-4o-mini")
MAX_ATTEMPTS = 3
MAX_ACCEPTABLE_WAIT = 60.0


def parse_retry_after(header_value: str | None) -> float | None:
    if not header_value:
        return None
    raw = header_value.strip()
    if raw.isdigit():
        return max(0.0, float(raw))
    try:
        parsed_date = email.utils.parsedate_to_datetime(raw)
        delay = parsed_date.timestamp() - time.time()
        return max(0.0, delay)
    except Exception:
        return None


def execute_completion(prompt_text: str) -> str | None:
    if not API_KEY:
        sys.stderr.write("Переменная окружения OPENROUTER_API_KEY не задана.\n")
        return None

    endpoint = "https://openrouter.ai/api/v1/chat/completions"
    payload = json.dumps(
        {
            "model": MODEL_ID,
            "messages": [{"role": "user", "content": prompt_text}],
        }
    ).encode("utf-8")

    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    }

    for attempt in range(1, MAX_ATTEMPTS + 1):
        req = urllib.request.Request(endpoint, data=payload, headers=headers, method="POST")
        try:
            with urllib.request.urlopen(req, timeout=30) as response:
                status_code = response.getcode()
                body = response.read().decode("utf-8")
                if status_code == 200:
                    data = json.loads(body)
                    return data["choices"][0]["message"]["content"]
        except urllib.error.HTTPError as err:
            if err.code == 429:
                retry_header = err.headers.get("Retry-After")
                server_delay = parse_retry_after(retry_header)

                if server_delay is not None:
                    wait_seconds = server_delay
                else:
                    base_delay = 2.0 ** attempt
                    wait_seconds = base_delay + random.uniform(0.1, 1.0)

                if wait_seconds > MAX_ACCEPTABLE_WAIT:
                    sys.stderr.write(
                        f"Сервер запросил паузу {wait_seconds:.1f} с. "
                        "Ожидание превышает 60 секунд. Запрос отменен.\n"
                    )
                    return None

                if attempt == MAX_ATTEMPTS:
                    sys.stderr.write("Исчерпан лимит из 3 попыток на статус 429.\n")
                    return None

                sys.stderr.write(
                    f"Получен 429. Попытка {attempt} завершилась неудачей. "
                    f"Пауза {wait_seconds:.2f} с перед следующим запросом.\n"
                )
                time.sleep(wait_seconds)
                continue
            elif err.code == 402:
                sys.stderr.write("Ошибка 402: проверьте баланс счета и лимит ключа.\n")
                return None
            else:
                sys.stderr.write(f"HTTP-ошибка {err.code}: запрос отклонен без повтора.\n")
                return None
        except urllib.error.URLError as err:
            sys.stderr.write(f"Сетевой сбой: {err.reason}. Повтор отменен.\n")
            return None

    return None


if __name__ == "__main__":
    result = execute_completion("Назови три базовых принципа надежности сетевых API.")
    if result:
        print(result)

Como o script acima preserva suas strings de log de diagnóstico originais em russo byte a byte, apresentamos a seguir a explicação de sua árvore de decisão interna e os equivalentes localizados:

  • Переменная окружения OPENROUTER_API_KEY не задана. (A variável de ambiente OPENROUTER_API_KEY não foi definida): Indica que a variável de ambiente OPENROUTER_API_KEY está ausente; a função é interrompida imediatamente sem efetuar chamadas de rede.
  • Сервер запросил паузу ... с. Ожидание превышает 60 секунд. Запрос отменен. (O servidor solicitou uma pausa de … s. A espera ultrapassa 60 segundos. Requisição cancelada.): Disparado quando o header Retry-After do servidor exige uma espera superior a MAX_ACCEPTABLE_WAIT (60 segundos); a execução é cancelada de imediato em vez de bloquear processos concorrentes indefinidamente.
  • Исчерпан лимит из 3 попыток на статус 429. (Limite de 3 tentativas esgotado para o status 429.): Indica que todas as 3 tentativas de repetição foram esgotadas diante de respostas HTTP 429.
  • Получен 429. Попытка ... завершилась неудачей. Пауза ... с перед следующим запросом. (Recebido 429. A tentativa … falhou. Pausa de … s antes da próxima requisição.): Registra uma falha intermediária de limite de taxa 429 na tentativa correspondente e suspende a execução pelo período calculado antes de reenviar a requisição.
  • Ошибка 402: проверьте баланс счета и лимит ключа. (Erro 402: verifique o saldo da conta e o limite da chave.): Registra um erro irrecuperável de pagamento HTTP 402 indicando que o saldo da conta está esgotado ou que o teto da chave foi atingido; nenhuma nova tentativa é efetuada.
  • HTTP-ошибка ...: запрос отклонен без повтора. (Erro HTTP …: requisição rejeitada sem repetição.): Registra qualquer outro código de status HTTP e encerra a rotina sem novas tentativas.
  • Сетевой сбой: ... Повтор отменен. (Falha de rede: … Repetição cancelada.): Captura falhas gerais de socket ou rede (URLError) e encerra a execução para evitar o reenvio de chamadas quando não há certeza se o payload foi ou não recebido e processado pelo servidor.
  • O prompt de teste "Назови три базовых принципа надежности сетевых API." traduz-se como “Cite três princípios básicos de confiabilidade de APIs de rede.”

Repetição de Requisições de Rede e Efeitos Colaterais

Ao projetar fluxos de trabalho com chamada de ferramentas (tool calling) dentro de loops de agentes autônomos, a repetição de requisições HTTP exige extremo cuidado. Se o modelo já tiver acionado uma ferramenta externa no passo anterior que alterou o estado do sistema (como gravação em banco de dados, envio de pagamento ou abertura de ticket), repetir a cadeia inteira causará execuções duplicadas. Em hipótese alguma as chamadas devem ser repetidas automaticamente se ferramentas de negócio vinculadas já tiverem sido executadas, ou diante de resultados de rede ambíguos (como quedas de conexão ou timeouts de socket em que não se sabe se o servidor chegou a receber e processar o prompt).

No exemplo apresentado acima, a repetição é realizada estritamente para requisições explicitamente rejeitadas pelo modelo com o status HTTP 429. Além disso, a geração de texto nunca deve ser considerada estritamente idempotente ou gratuita: o reenvio de chamadas consome cotas adicionais de tokens e orçamento, enquanto a natureza estocástica dos modelos pode produzir respostas distintas. Se ocorrer uma falha no momento em que um agente executa um comando externo, o estado do sistema deve ser sincronizado por meio de um log de ações antes de restabelecer o diálogo com o modelo.

Construção de Arquiteturas de Roteamento Resilientes

Na página de preços, o plano Free estabelece um limite da plataforma de 50 requisições diárias para modelos gratuitos. É crucial pontuar que a ausência de limites da plataforma destacada na documentação refere-se à migração para modelos pagos, e não simplesmente à compra de créditos — recarregar o saldo não remove automaticamente as restrições dos endpoints :free. As condições vigentes e a variabilidade de cotas para a sua conta devem sempre ser conferidas na tabela de limites atualizada. Além disso, mesmo a utilização de modelos pagos não elimina por completo a sobrecarga eventual em clusters de servidores dos provedores (e, embora alternar entre provedores possa ajudar a mitigar a indisponibilidade, isso não garante a recuperação imediata).

Para assegurar confiabilidade operacional em ambientes de produção, as equipes de engenharia costumam combinar as seguintes estratégias defensivas:

  • Especificar modelos de fallback no array de parâmetros models da requisição ao OpenRouter, permitindo que o roteador redirecione automaticamente a chamada a um executor reserva caso a opção principal falhe.
  • Limitar a quantidade máxima de requisições simultâneas no lado do cliente por meio de filas de tarefas, limitadores de taxa ou algoritmos de token bucket.
  • Manter uma rota de backup independente via APIs multimodelo alternativas com esquemas de requisição compatíveis para partes críticas da infraestrutura, viabilizando o redirecionamento de tráfego durante períodos prolongados de indisponibilidade do gateway principal.

Quer otimizar seu fluxo de trabalho com LLMs?

Conecte modelos por uma única API, gerencie chaves e controle os gastos com IA.

Começar grátis