Receber um 429 no OpenRouter não significa, necessariamente, que sua conta atingiu algum limite da plataforma. O bloqueio também pode vir do provedor upstream escolhido para a inferência. Antes de alterar a chave, comprar créditos ou adicionar tentativas automáticas, salve uma resposta completa que falhou: status HTTP, cabeçalhos e corpo JSON revelam qual limite precisa ser tratado.
Antes de mudar qualquer coisa, analise uma resposta 429
Classifique a falha antes de comprar créditos, trocar a chave ou implementar retries. Os campos tipados e os cabeçalhos da resposta do OpenRouter são evidências mais confiáveis que a mensagem legível, pois ela pode incluir texto encaminhado pelo provedor upstream.
| Evidência | Origem mais provável | Próxima ação |
|---|---|---|
HTTP 429 com X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset | Limite da plataforma OpenRouter | Aguarde até o reset e reduza a taxa de requisições ou a concorrência |
error.metadata.error_type é rate_limit_exceeded, com detalhes do provedor, como provider_code | Provedor upstream | Aguarde, permita outro provedor ou use um fallback de modelo |
Retry-After está presente | Todos os provedores tentados forneceram uma indicação de espera | Aguarde esse intervalo antes da próxima tentativa |
| HTTP 402 | Saldo insuficiente ou teto de crédito por chave esgotado | Adicione crédito ou altere o teto da chave; backoff de retry não resolverá |
HTTP 200, seguido de erro SSE e finish_reason: "error" | Falha após o início do streaming | Considere o stream como falho e inspecione o tipo de erro incorporado |
A referência de erros e depuração do OpenRouter define o envelope com error.code, error.message e o opcional error.metadata, incluindo error_type = "rate_limit_exceeded". Ela também informa que respostas bem-sucedidas normalmente não incluem X-RateLimit-*. A sobrecarga do provedor é tipada separadamente como provider_overloaded e, em geral, corresponde ao status 503.
Como resolver um 429 do próprio OpenRouter
Um 429 gerado pelo OpenRouter é controlado pela cota da plataforma associada à conta e à classe do modelo. Conforme verificado na documentação oficial de limites de taxa em 31 de julho de 2026, variantes gratuitas terminadas em :free possuem limites por minuto e por dia.
| Cota de modelos gratuitos | Limite atual |
|---|---|
| Requisições por minuto | 20 RPM |
| Requisições diárias com menos de US$ 10 em compras de crédito acumuladas | 50 RPD |
| Requisições diárias com pelo menos US$ 10 em compras de crédito acumuladas | 1.000 RPD |
A política de limites afirma que contas ou chaves extras não ampliam a capacidade governada globalmente. Portanto, substituir uma chave válida não reinicia um limite de taxa da plataforma.
Use o endpoint GET /api/v1/key para verificar uso e limites de crédito:
curl https://openrouter.ai/api/v1/key \
-H "Authorization: Bearer $OPENROUTER_API_KEY"
Em caso de 429 da plataforma, use o cabeçalho de reset da resposta de erro e aplique estas mudanças nesta ordem:
- Interrompa as tentativas imediatas e aguarde até
X-RateLimit-Reset. - Reduza as requisições simultâneas, não apenas as requisições por segundo. Um pico de workers paralelos pode ultrapassar o limite antes que qualquer worker veja o primeiro 429.
- Coloque o trabalho em uma fila atrás de um limitador compartilhado, evitando que todos os workers despertem e tentem novamente ao mesmo tempo.
- Se a carga de trabalho não couber na cota de modelos gratuitos, direcione esse tráfego para uma variante paga adequada.
Saldo negativo ou teto de crédito por chave esgotado devem gerar 402, enquanto um provedor upstream ainda pode retornar 429 para uma conta com saldo. O guia de preços do OpenRouter aborda separadamente custos e créditos.
Como resolver o 429 de “Provider Returned Error”
Um 429 retornado pelo provedor indica que o OpenRouter conseguiu chegar a um provedor upstream de inferência, mas ele não aceitou a requisição naquele momento. Procure o valor tipado de limite de taxa e os metadados do provedor: adicionar crédito ao OpenRouter não cria capacidade nesse provedor.
A referência oficial de limites informa que o roteamento pode já ter tentado provedores alternativos antes de devolver o erro. Ela também adiciona Retry-After quando todos os provedores tentados forneceram uma indicação de retry. Na prática, faça o seguinte:
- Respeite
Retry-Afterem vez de regenerar imediatamente a mesma solicitação. - Remova restrições excessivamente rígidas de provedores caso elas deixem apenas uma rota congestionada.
- Confirme que o fallback de provedor está permitido para a requisição.
- Configure um fallback de modelo quando concluir a tarefa for mais importante que usar exatamente aquele modelo.
Um usuário do Zed com saldo recebeu um limite upstream em moonshotai/kimi-k2:free, e regenerar a chave não ajudou. Um colaborador do Zed explicou:
“Isso não é um erro do Zed; é o OpenRouter dizendo que o provedor upstream que você está usando está limitando sua taxa de requisições.” Fonte: zed-industries/zed issue #35153
Respeite um Retry-After curto. Use um fallback de modelo gratuito apenas quando concluir a tarefa for mais importante que manter o modelo exato.
Quando o erro aparece no Janitor AI, Zed ou SillyTavern
Preserve o erro bruto, evite regenerações repetidas e altere o modelo ou a rota permitida em falhas do lado do provedor. Insira a chave novamente apenas para corrigir o armazenamento no cliente; isso não reinicia a capacidade disponível.
Como fazer retry sem entrar em um ciclo de 429
Repita somente falhas por limite de taxa, limite a quantidade de tentativas e dê preferência ao tempo de espera solicitado pelo servidor. Quando não houver indicação de retry, use backoff exponencial com teto e jitter para que clientes paralelos não se sincronizem em outro pico de requisições.
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
function retryDelayMs(response, attempt) {
const retryAfter = response.headers.get("retry-after");
if (retryAfter) {
const seconds = Number(retryAfter);
if (Number.isFinite(seconds)) return Math.max(0, seconds * 1000);
const dateMs = Date.parse(retryAfter);
if (Number.isFinite(dateMs)) return Math.max(0, dateMs - Date.now());
}
const capMs = 30_000;
const exponentialMs = Math.min(capMs, 1000 * 2 ** attempt);
return Math.random() * exponentialMs; // Full jitter
}
async function createChatCompletion(body, maxAttempts = 4) {
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
const response = await fetch(
"https://openrouter.ai/api/v1/chat/completions",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
},
);
const raw = await response.text();
let payload;
try {
payload = raw ? JSON.parse(raw) : null;
} catch {
payload = null;
}
if (response.ok) return payload;
const isRateLimit =
response.status === 429 ||
payload?.error?.metadata?.error_type === "rate_limit_exceeded";
if (!isRateLimit || attempt === maxAttempts - 1) {
const error = new Error(payload?.error?.message || raw || `HTTP ${response.status}`);
error.status = response.status;
error.details = payload?.error;
throw error;
}
await sleep(retryDelayMs(response, attempt));
}
}
Esta função lida com respostas sem streaming. Mantenha o controle de concorrência por fila compartilhada ou token bucket fora dela, para que muitos workers em espera não reiniciem juntos.
Quando os Server-Sent Events começam com HTTP 200, o status não pode mudar para 429. A referência de erros do OpenRouter informa que uma falha posterior chega no stream com um erro e finish_reason: "error". Marque a conclusão como falha e repita somente se o tipo incorporado for rate_limit_exceeded. Não devolva o texto acumulado como sucesso, a menos que a aplicação ofereça suporte explícito a resultados parciais.
Perguntas frequentes
O que significa o erro 429 provider returned error no OpenRouter?
Um provedor upstream de inferência recusou a requisição devido ao próprio limite de taxa ou de capacidade. Confirme isso com error.metadata.error_type e os metadados do provedor.
Por que recebo 429 no OpenRouter mesmo tendo créditos?
Uma conta com saldo pode receber um 429 do lado do provedor. Já saldo insuficiente ou um teto de crédito por chave normalmente resulta em 402.
Criar uma nova chave de API do OpenRouter reinicia o limite de taxa?
Não. Chaves adicionais não aumentam limites governados globalmente; substitua uma chave apenas para corrigir autenticação ou armazenamento no cliente.
Quanto tempo devo esperar antes de tentar o OpenRouter novamente?
Use Retry-After quando ele estiver presente. Para um limite da plataforma, use X-RateLimit-Reset. Sem nenhuma dessas indicações, aplique backoff exponencial com teto, jitter e um número máximo pequeno de tentativas.
O OpenRouter pode retornar HTTP 200 e ainda falhar com 429?
Sim, quando o streaming já começou. O status HTTP permanece 200, enquanto o stream SSE informa um erro e termina com finish_reason: "error". Inspecione o tipo de erro incorporado para determinar se houve limite de taxa.