HiAPI
Blog

Tutoriel

URL de sortie des tâches HiAPI expirée (expireAt) : téléchargez et archivez le résultat avant son invalidation

output[].url en état final porte un expireAt, une fois expiré c'est 404 — comment le détecter, comment télécharger à temps, comment récupérer après expiration.

Oct 22, 2026
URL de sortie des tâches HiAPI expirée (expireAt) : téléchargez et archivez le résultat avant son invalidation

Vous générez une image ou une vidéo avec POST /v1/tasks, et une fois la tâche terminée vous récupérez depuis data.output[0].url un lien temp.hiapi.ai — il s'ouvre à ce moment-là, mais quelques jours plus tard il renvoie une page HTML « Not Found » :

HTTP/2 404
content-type: text/html

Ce ne sont pas les octets de l'image/la vidéo qui sont renvoyés, mais une page 404 de Cloudflare. La cause est unique : l'URL de sortie des tâches est un lien temporaire avec une durée de validité, dès que expireAt (timestamp Unix) de l'état final est atteint, l'objet sur temp.hiapi.ai est purgé et le lien ne fonctionne plus.

Comprendre les champs de l'état final

Lorsque le polling de l'état final d'une tâche (GET /v1/tasks/{taskId}) réussit, les champs clés ressemblent à ceci :

{
  "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" est le seul état final de succès (l'échec est "fail", la file d'attente/le traitement est queued / handling / archiving).
  • data.output est un tableau, chaque élément porte son propre url et son propre expireAt.
  • expireAt est un timestamp Unix entier (pas une chaîne ISO). Pour déterminer l'expiration, on se fie uniquement à lui : now >= expireAt signifie expiré.
  • La valeur de data.storage est "temp" — c'est en soi un indice : c'est du stockage temporaire, pas destiné à une référence à long terme.

Quelle est la durée de validité ? Sur un échantillon mesuré, expireAt - completed = 604800 secondes (soit exactement 7 jours). Mais ne codez pas « 7 jours » en dur — fiez-vous au expireAt propre à chaque sortie, les différents modèles/stratégies de stockage pouvant varier.

Causes courantes (classées par probabilité d'occurrence)

  1. Avoir stocké le lien temporaire en base de données pour une référence à long terme : lors de l'insertion, c'est l'URL temporaire temp.hiapi.ai/... qui est enregistrée, et au-delà de expireAt tout part en 404. C'est le piège le plus fréquent.
  2. Ne pas avoir téléchargé immédiatement après l'état final : récupérer les octets longtemps après la fin de la tâche (au-delà du TTL).
  3. Croire qu'un nouveau polling peut « rafraîchir » le lien : un nouveau GET sur le même taskId renvoie la même url et le même expireAt — les métadonnées persistent, mais l'objet lui-même ne se régénère pas après expiration, un nouveau GET ne vous donnera pas de nouveau lien.
  4. Confondre le 404 avec un échec de tâche : la tâche est en fait success depuis longtemps, seule l'asset de sortie a expiré, ce sont deux choses distinctes.

Étapes de correction

  1. Dès l'état final, téléchargez immédiatement les octets. Après avoir détecté data.status == "success" par polling, envoyez aussitôt un GET sur chaque output[].url pour récupérer le binaire, sans file d'attente ni report.
  2. Archivez vers votre propre stockage objet (R2 / S3 / disque local), et remplacez par votre propre URL persistante.
  3. Ne stockez en base de données que votre propre URL persistante, jamais le lien temporaire temp.hiapi.ai.
  4. Vérifiez l'expiration avant de télécharger : téléchargez seulement si now < expireAt ; si déjà expiré, passez directement à la logique de relance.
  5. Si expiré, seule la relance de la tâche est possible. Il n'existe pas de « échange du taskId contre un nouveau lien » — un nouveau GET sur le même taskId renvoie toujours cette url invalide. Pour obtenir à nouveau un résultat téléchargeable, il faut soumettre une nouvelle fois la tâche (facturation à nouveau).
  6. Contrôlez le timing des téléchargements pour les tâches en lot : parmi un lot, la tâche terminée en premier a aussi le expireAt le plus précoce. Téléchargez immédiatement par ordre d'achèvement, n'attendez pas que tout le lot soit terminé pour télécharger en une fois, sinon les premières terminées risquent d'être proches de l'expiration.

Exemple de vérification minimal

Confirmez que votre clé fonctionne, que l'API de tâches produit un résultat, et voyez de vos yeux expireAt. Utilisez l'id brut du modèle (z-image, sans suffixe du type /text-to-image, sinon 400) :

# 1. Soumettre la tâche
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. Faire du polling de l'état final avec le taskId de l'étape précédente, lire url et expireAt
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-xxxx \
  -H "Authorization: Bearer $HIAPI_API_KEY"
# Une fois data.status passé à "success", data.output[0].url / .expireAt sont disponibles

Si l'authentification échoue, la réponse est HTTP 401 + {"error":{"code":"permission_denied","type":"hiapi_error","request_id":"..."}} — c'est un problème de clé, pas d'expiration. Si la tâche est introuvable, c'est {"code":404,"data":null,"message":"task not found"} — généralement un taskId mal recopié ou une clé d'un autre environnement.

Liens associés

FAQ

Q : Quel est exactement le format de expireAt ? R : Un timestamp Unix entier (secondes), par exemple 1792432981, pas une chaîne ISO. Utilisez now >= expireAt pour déterminer l'expiration.

Q : Après expiration du lien, peut-on faire un nouveau GET de la tâche pour « prolonger » le lien ? R : Non. Un nouveau GET sur le même taskId renvoie toujours cette url d'origine et ce expireAt d'origine, l'objet ayant été purgé. Pour obtenir à nouveau un résultat téléchargeable, il faut relancer la tâche (facturation à nouveau).

Q : Après expiration, l'accès renvoie-t-il 403 ou 404 ? R : C'est HTTP 404, et le body est une page Cloudflare « Not Found » en text/html, ni des octets d'image, ni un AccessDenied XML. Si votre logique de téléchargement n'accepte que 200, pensez à traiter « tout ce qui n'est pas 200 » comme un échec.

Q : La durée de validité est-elle fixe à 7 jours ? R : Sur l'échantillon mesuré c'est 7 jours (604800 secondes), mais fiez-vous au expireAt propre à chaque sortie, n'écrivez pas le nombre de jours en dur dans le code.

Q : Comment télécharger un lot de tâches de la manière la plus sûre ? R : Par ordre d'achèvement, celui qui passe en success en premier voit ses octets téléchargés en premier. La sortie terminée en premier a aussi le expireAt le plus précoce ; tout regrouper à la fin risque de tomber sur des échéances proches.

Articles similaires

Voir tous les articles →

Commencez avec des artefacts IA persistants

Obtenez votre clé API et appelez des modèles d'image, de vidéo et d'audio via une API unique basée sur les tasks.

Lire la documentation de l'API