Tutorial
Corrigir erros de limite de taxa (429) do HiAPI: causas e soluções
Quando o gateway do HiAPI retorna HTTP 429 Too Many Requests, isso significa que a sua API Key excedeu, em um curto intervalo de tempo, a frequência de requisições ou o limite de concorrência permitido em https://api.hiapi.ai/v1/tasks (ou no endpoint de polling GET /v1/tasks/{taskId}). O corpo da resposta segue o envelope de erro unificado do HiAPI — {"error":{"type":"hiapi_error","code":"...","request_id":"..."}} — acompanhado de um status code 429. Resolver isso quase nunca exige enviar e-mail ao suporte; na prática, basta adicionar uma pequena camada de «retry + rate limiting» no cliente. Este artigo explica o que é esse erro, por que ele é disparado e os passos concretos para fazê-lo desaparecer.
Como é um 429 do HiAPI
Uma requisição típica, na camada de rede, se parece mais ou menos assim:
> POST /v1/tasks HTTP/1.1
> Host: api.hiapi.ai
> Authorization: Bearer hi-sk-...
> Content-Type: application/json
< HTTP/1.1 429 Too Many Requests
< Content-Type: application/json
<
{"error":{"type":"hiapi_error","code":"rate_limit_exceeded","request_id":"req_..."}}
Dois pontos importantes:
- O status code é
429, não401/403.401indica que a Key está incorreta ou ausente;429indica que a Key está correta, mas você está enviando requisições rápido demais. Não confunda os dois. - O corpo da resposta é um JSON no envelope
hiapi_error. Alguns clientes HTTP expõem apenas o status code por padrão; se o seu código faz retry silencioso sem registrar logs, você perde pistas de diagnóstico como orequest_id.
Se você chama modelos como GPT Image 2, Nano-Banana, flux, Seedance, Wan ou HappyHorse, todos eles rodam no mesmo endpoint de tarefas assíncronas e, portanto, compartilham a mesma contabilização de taxa por Key.
Causas comuns (ordenadas por probabilidade)
Segundo a nossa experiência, da mais para a menos provável:
- Fan-out em rajada (burst fan-out) com uma única Key. Você percorre um lote de prompts e chama
POST /v1/tasksconcorrentemente para cada um, sem limite de concorrência. Mesmo cerca de uma dezena de criações de tarefas concorrentes já é suficiente para atingir o teto em uma conta nova. - Polling agressivo em
GET /v1/tasks/{taskId}. Um loop apertado do tipowhile True: poll(); sleep(0.2)conta como volume de requisições tanto quanto a criação de tarefas. Polling em intervalo subsegundo é a causa número um de «criei só uma tarefa e ainda assim recebo 429». - Limite de concorrência no nível da conta. Modelos mais pesados — vídeo (
seedance-2.0,wan2.7-video/*,happyhorse-1.0) e variantes de imagem@pro— entram em limites de tarefas concorrentes mais rígidos. Submeter muitos desses de uma vez provoca 429 mesmo que sua frequência por minuto não seja alta. - Uma mesma Key compartilhada entre múltiplos ambientes. dev, staging e prod usam o mesmo
HIAPI_API_KEY, e os volumes se somam. Cada ambiente isolado parece ok, mas juntos empurram a Key acima do limite. - Cota do plano esgotada. Cota gratuita ou plano pago próximo do esgotamento às vezes se manifesta como 429 em vez de erro de cobrança, especialmente durante promoções.
Sobre os limites concretos: o número de requisições por minuto e o limite de concorrência do HiAPI dependem do nível da sua conta, e a plataforma não divulga um número fixo. Portanto, os valores de concorrência abaixo (5, 3, 2) são pontos de partida empíricos, não limites oficiais — ajuste com base no uso real exibido no dashboard.
Passos de correção
Siga na ordem. A maioria das equipes deixa de receber alertas ao chegar ao passo 3.
1. Adicione backoff exponencial com jitter
Qualquer cliente que se comunique com api.hiapi.ai deve, ao receber 429, tentar novamente com atraso crescente — nunca tentar imediatamente. Uma implementação padrão segura:
import random, time, requests
def post_task_with_backoff(body, key, *, max_retries=5):
delay = 1.0
for attempt in range(max_retries):
r = requests.post(
"https://api.hiapi.ai/v1/tasks",
headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
json=body, timeout=30,
)
if r.status_code != 429:
r.raise_for_status()
return r.json()
retry_after = r.headers.get("Retry-After")
wait = float(retry_after) if retry_after else delay + random.random()
time.sleep(min(wait, 30.0))
delay = min(delay * 2, 30.0)
raise RuntimeError("rate-limited after retries")
Esse código acerta em duas coisas: limita o atraso a 30 segundos e prioriza o cabeçalho Retry-After quando presente. Mesmo que a sua resposta 429 não traga Retry-After, a estratégia de «teto + jitter» já consegue absorver a maioria das rajadas.
2. Limite a concorrência do cliente por Key
Adicionar um semáforo no cliente é a mudança individual mais eficaz. Se não souber qual valor usar, comece com 5:
import asyncio, httpx
sem = asyncio.Semaphore(5)
async def create_task(client, body):
async with sem:
r = await client.post("https://api.hiapi.ai/v1/tasks", json=body, timeout=30)
return r.json()
Rodar 5 tarefas ao mesmo tempo é tranquilo para a maioria das contas. Se ainda houver 429, reduza para 3. Modelos pesados de vídeo normalmente exigem um semáforo separado e mais baixo (tente 2).
3. Troque o polling por callback.url
Para cargas de produção, fazer polling em GET /v1/tasks/{taskId} não é um bom padrão. Passe callback.url no corpo da requisição e o HiAPI fará um POST com o resultado para você quando a tarefa atingir o estado final:
{
"model": "Nano-Banana",
"input": { "prompt": "a calm lake at dawn", "aspect_ratio": "16:9" },
"callback": { "url": "https://your-domain.com/hiapi/callback", "when": "final" }
}
Isso comprime o padrão de requisições O(número de tarefas × número de polls) para O(número de tarefas) — normalmente uma redução de 10 a 50 vezes no volume de chamadas, e o antídoto quase imediato para 429 causado por polling. Deixe GET /v1/tasks/{taskId} apenas para depuração local e chamadas pontuais de baixa frequência.
4. Desacelere o ritmo do polling e adicione jitter
Se você não puder usar callback (scripts offline, notebook local, reconciliação de contingência), então não faça polling mais rápido que a cada 2–5 segundos e adicione jitter para evitar que vários workers andem em sincronia:
import random, time
time.sleep(2 + random.random() * 3) # 2–5 segundos, com jitter
5. Separe as Keys por ambiente
Na página de chaves de API do HiAPI, gere uma Key para cada ambiente — dev, staging, prod. As rajadas de cada ambiente ficam isoladas entre si, e se uma Key vazar pode ser revogada individualmente sem afetar os outros ambientes.
6. Verifique o uso atual
Abra o dashboard do HiAPI para confirmar se você atingiu o limite de concorrência/plano ou se foi apenas uma rajada breve; as cotas de cada nível de plano podem ser comparadas na página de preços. Se o uso estiver bem abaixo do plano e ainda assim houver 429, a causa é quase certamente uma rajada no lado do cliente, não a conta em si.
Verificação mínima
Com a camada de retry pronta, usar uma tarefa Nano-Banana é a forma mais barata de confirmar se a comunicação está funcionando. Substitua $HIAPI_API_KEY pela sua Key:
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "Nano-Banana",
"input": { "prompt": "a single red apple on a white table", "aspect_ratio": "1:1" }
}'
O sucesso se parece mais ou menos assim: {"code":200,"data":{"taskId":"tk-hiapi-..."}}. Em seguida, faça um poll:
curl -s -H "Authorization: Bearer $HIAPI_API_KEY" \
https://api.hiapi.ai/v1/tasks/tk-hiapi-...
O status passa por queued → handling → archiving → success, e o data.output[0].url final é a sua imagem. Se esse único ciclo retorna 200, mas suas tarefas em lote continuam recebendo 429, o problema está na concorrência do cliente, não na sua Key.
Perguntas frequentes
Por que recebo 429 mesmo tendo enviado apenas uma requisição?
Quase sempre porque o volume real de requisições vem do loop de polling, não da criação de tarefas. Fazer polling a cada 200ms em 5 tarefas concorrentes já dá 25 requisições por segundo só nisso. Reduza o polling para 2–5 segundos ou use callback.url.
O HiAPI sempre envia o cabeçalho Retry-After?
Trate Retry-After como sugestão: use-o se existir; caso contrário, recorra ao backoff exponencial (1s, 2s, 4s… com teto de 30s). De qualquer forma, não tente novamente sem atraso — isso só amplia a rajada.
429 e 401 / 403 são a mesma coisa?
Não. 401 / 403 indicam falha de autenticação, também no mesmo envelope hiapi_error, por exemplo {"error":{"code":"permission_denied","type":"hiapi_error","request_id":"req_..."}} (na prática, o message de um 401 traz algo como "This API key is invalid. Check that it is correct..."). Se você vê 401/403, confira o valor da Key na página de chaves de API — backoff não resolve isso.
Posso simplesmente aumentar o limite de taxa?
Se o seu tráfego realmente precisa de um limite de concorrência maior, primeiro confirme a cota do plano na página de preços e depois entre em contato com o suporte por lá. Na prática, as correções acima resolvem mais de 90% dos problemas de 429 sem alterar nenhum limite.
Qual é a diferença entre um 429 em /v1/tasks e um 429 em /v1/tasks/{taskId}?
O endpoint só indica o que você estava fazendo naquele momento — ambos compartilham o mesmo orçamento de taxa por Key. O 429 no endpoint de criação aponta para fan-out (limite a concorrência, mude o processamento em lote); o 429 no endpoint de polling aponta para um loop de polling apertado (desacelere ou mude para callback). A estrutura completa de requisição/resposta está no HiAPI Quickstart e na documentação de autenticação.
Resumo
429 é um sinal normal e recuperável que qualquer gateway de API de nível de produção emite. Adicione backoff exponencial, limite a concorrência do cliente, substitua polling por callback e confirme o uso no dashboard. Feitas essas quatro coisas, você pode simplesmente parar de pensar em 429. Esta página é a versão em português do original em inglês «How to Fix HiAPI Rate Limit (429) Errors», com os detalhes técnicos mantidos em conformidade com o original.
Artigos relacionados
Ver todos os artigos →-
Tutorial
Como chamar hailuo-2.3-fast/image-to-video pela API HiAPI: curl e Python na prática
A primeira requisição executável do nível rápido e econômico de geração de vídeo a partir de imagem — do ID do modelo ao download do MP4
-
Tutorial
Como chamar hailuo-2.3/text-to-video pela API HiAPI: curl, Python e exemplos de requisição executáveis
-
Tutorial
Usar Kandinsky 6.0 Pro text-to-video na HiAPI: tutorial de curl e Python
Demonstração prática com foco na requisição: montar a chamada de prompt para clipe de vídeo, enviar a requisição, consultar o status de conclusão e baixar o resultado