HiAPI
Blogue

Tutorial

URL de saída da tarefa HiAPI expirada (expireAt): baixe e transfira o resultado antes que ele expire

O output[].url no estado final traz expireAt; ao expirar, retorna 404 — como identificar, baixar a tempo e recuperar após a expiração.

Oct 22, 2026
URL de saída da tarefa HiAPI expirada (expireAt): baixe e transfira o resultado antes que ele expire

Você gera uma imagem ou vídeo com POST /v1/tasks e, após a tarefa concluir, obtém de data.output[0].url um link de temp.hiapi.ai — que abre na hora, mas ao acessar alguns dias depois vira uma página HTML de "Not Found":

HTTP/2 404
content-type: text/html

O retorno não são os bytes da imagem/vídeo, mas a página 404 da Cloudflare. O motivo é um só: a URL de saída da tarefa é um link temporário com validade; assim que o expireAt (timestamp Unix) do estado final chega, o objeto em temp.hiapi.ai é removido e o hotlink deixa de funcionar.

Primeiro, entenda os campos do estado final

Quando o polling do estado final da tarefa (GET /v1/tasks/{taskId}) é bem-sucedido, os campos-chave ficam assim:

{
  "code": 200,
  "data": {
    "taskId": "tk-hiapi-xxxxxxxx",
    "status": "success",
    "storage": "temp",
    "created": 1791828181,
    "completed": 1791828201,
    "output": [
      {
        "artifactId": "...",
        "type": "image",
        "url": "https://temp.hiapi.ai/....png",
        "expireAt": 1792432981
      }
    ]
  },
  "message": "success"
}
  • data.status == "success" é o estado final de sucesso (falha é "fail"; em fila/processando são queued / handling / archiving).
  • data.output é um array, e cada elemento traz seu próprio url e expireAt.
  • expireAt é um timestamp Unix inteiro (não é string ISO). Para saber se expirou, olhe só para ele: now >= expireAt significa expirado.
  • O valor de data.storage é "temp" — o que já é uma dica: é armazenamento temporário, não para referência de longo prazo.

Qual é a duração da validade? Em uma amostra medida, expireAt - completed = 604800 segundos (exatamente 7 dias). Mas não hardcode "7 dias" no código — use o expireAt de cada saída como referência, pois modelos/estratégias de armazenamento diferentes podem variar.

Causas comuns (ordenadas por probabilidade)

  1. Salvar o hotlink no banco de dados para referência de longo prazo: ao persistir, guarda-se a URL temporária temp.hiapi.ai/..., e após o expireAt tudo vira 404 em massa. Esta é a armadilha mais comum.
  2. Receber o estado final e não baixar imediatamente: buscar os bytes muito tempo depois (além do TTL) da conclusão da tarefa.
  3. Achar que refazer o polling "renova" o link: fazer GET de novo no mesmo taskId retorna a mesma url e o mesmo expireAt — os metadados persistem, mas o objeto em si não é regenerado após expirar; um novo GET não dá um novo link.
  4. Confundir 404 com falha da tarefa: a tarefa na verdade já estava success há tempos, apenas o asset de saída expirou; são duas coisas distintas.

Passos de correção

  1. Assim que o estado final chegar, baixe os bytes imediatamente. Após o polling retornar data.status == "success", faça GET em cada output[].url e baixe o binário na hora — não enfileire, não adie.
  2. Transfira para o seu próprio armazenamento de objetos (R2 / S3 / disco local), trocando por uma sua URL persistente.
  3. No banco de dados, guarde apenas a sua URL persistente; nunca armazene o hotlink temp.hiapi.ai.
  4. Antes de baixar, valide se não expirou: baixe só se now < expireAt; se já expirou, vá direto para a lógica de reexecução.
  5. Se expirou, só resta reexecutar a tarefa. Não existe "trocar taskId por um novo link" — um novo GET no mesmo taskId retorna a mesma url inválida. Para obter novamente um resultado baixável, é preciso reenviar a tarefa (nova cobrança).
  6. Em tarefas em lote, controle a ordem dos downloads: a primeira a concluir no lote tem o expireAt mais cedo. Baixe imediatamente na ordem de conclusão; não espere o lote inteiro terminar para baixar tudo de uma vez, senão as que concluíram antes podem estar perto de expirar.

Exemplo mínimo de verificação

Confirme que sua key funciona, que a API de tarefas retorna resultado e veja o expireAt com seus próprios olhos. Use o model id puro (z-image, sem sufixos como /text-to-image, que causam 400):

# 1. Enviar a tarefa
curl -s https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "z-image",
    "input": { "prompt": "a red apple on a wooden table" }
  }'
# → {"code":200,"data":{"taskId":"tk-hiapi-..."},"message":"success"}

# 2. Fazer polling do estado final com o taskId do passo anterior e ler url e expireAt
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-xxxx \
  -H "Authorization: Bearer $HIAPI_API_KEY"
# depois que data.status vira "success", data.output[0].url / .expireAt já estão disponíveis

Se a autenticação falhar, o retorno é HTTP 401 + {"error":{"code":"permission_denied","type":"hiapi_error","request_id":"..."}} — é problema de key, não de expiração. Se a tarefa não for encontrada, é {"code":404,"data":null,"message":"task not found"} — geralmente taskId copiado errado ou key de ambiente errado.

Links relacionados

FAQ

P: Qual é o formato exato do expireAt? R: Timestamp Unix inteiro (segundos), por exemplo 1792432981, não é string ISO. Basta usar now >= expireAt para saber se expirou.

P: Depois que o link expira, dá para fazer GET de novo na tarefa para "renovar" o link? R: Não. Um novo GET no mesmo taskId retorna a mesma url original e o mesmo expireAt, e o objeto já foi removido. Para obter novamente um resultado baixável, só reexecutando a tarefa (nova cobrança).

P: Após expirar, o acesso retorna 403 ou 404? R: É HTTP 404, e o body é uma página "Not Found" da Cloudflare em text/html — não são bytes de imagem, nem um AccessDenied em XML. Se sua lógica de download só aceita 200, lembre-se de tratar "qualquer coisa diferente de 200 como falha".

P: A validade é fixa em 7 dias? R: Na amostra medida, 7 dias (604800 segundos), mas use o expireAt de cada saída como referência e não hardcode o número de dias no código.

P: Como baixar um lote de tarefas da forma mais segura? R: Na ordem de conclusão: quem fica success primeiro tem os bytes baixados primeiro. As saídas que concluem antes têm o expireAt mais cedo; deixar para baixar tudo no final tende a esbarrar em expiração iminente.

Artigos relacionados

Ver todos os artigos →

Comece a criar com artefactos de IA persistentes

Obtenha a sua chave de API e chame modelos de imagem, vídeo e áudio através de uma única API baseada em tasks.

Ler a documentação da API