> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aihubmix.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Tâches asynchrones

> API de tâches asynchrones AIHubMix : image avec async, vidéo, reprise après interruption LLM. Statut, résultats et rappels Webhook via /ai/v1/tasks.

La génération vidéo et la génération d'images par lots dépassent généralement la durée d'attente raisonnable d'une connexion HTTP. Pendant une génération de texte longue, si le client se déconnecte, la réponse déjà produite ne peut plus être récupérée.

Les **tâches asynchrones** (Async Tasks) réunissent ces trois scénarios autour d'un même objet tâche : les images et les vidéos créent une tâche via l'interface de génération et renvoient immédiatement un `task_id` ; les requêtes LLM interrompues côté client sont menées à leur terme par la plateforme, qui enregistre la réponse finale. Les trois partagent les mêmes statuts de tâche, la même interface d'interrogation et le même processus de téléchargement des résultats.

<Note>
  Utilisez la même clé API que celle ayant servi à créer la tâche pour interroger celle-ci et télécharger les résultats. Les tâches sont isolées par clé API : même si deux clés appartiennent au même compte, elles ne peuvent pas lire les tâches l'une de l'autre.
</Note>

<Card title="Activer les tâches asynchrones dans la console" icon="list-check" href="https://console.aihubmix.com/support" horizontal>
  Avant de créer une image ou une vidéo asynchrone, activez la fonctionnalité de tâches asynchrones pour le compte courant. Si l'entrée correspondante n'apparaît pas encore dans la console, contactez le support technique AIHubMix.
</Card>

<Warning>
  Lorsque la fonctionnalité de tâches asynchrones n'est pas activée, les requêtes de création de tâche média renvoient `403 async_not_enabled`. Les requêtes LLM ne renvoient pas d'erreur pour autant, mais la réponse finale ne peut pas être récupérée après une interruption du client.
</Warning>

***

<h2 id="quickstart">
  Démarrage rapide
</h2>

Le processus complet d'une tâche asynchrone d'image ou de vidéo comporte trois étapes :

```text theme={null}
1. Soumettre la tâche -> obtenir un task_id
2. Interroger le statut -> attendre la fin de la tâche
3. Récupérer le résultat -> télécharger le fichier ou lire le contenu de la réponse
```

<CodeGroup>
  ```shell curl theme={null}
  # Étape 1 : soumettre une tâche vidéo asynchrone
  curl -X POST https://aihubmix.com/ai/v1/videos \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "wan2.6-t2v",
      "prompt": "A cat playing jazz on a piano, warm lighting, cinematic shot",
      "seconds": "5",
      "size": "1280x720"
    }'

  # Étape 2 : interroger toutes les 15 secondes, jusqu'à ce que la tâche soit terminée, en échec ou annulée
  curl https://aihubmix.com/ai/v1/tasks/{task_id} \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY"

  # Étape 3 : télécharger un fichier produit
  curl https://aihubmix.com/ai/v1/tasks/{task_id}/content \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
    --output result.mp4
  ```

  ```json Réponse de création theme={null}
  {
    "id": "task_01K0...",
    "object": "video",
    "model": "wan2.6-t2v",
    "status": "in_progress",
    "output": [],
    "error": null,
    "created_at": 1784707200,
    "completed_at": null,
    "expires_at": null
  }
  ```
</CodeGroup>

***

<h2 id="sync-vs-async">
  Comparaison entre appel synchrone et tâche asynchrone
</h2>

| Type de requête         | Mode de retour par défaut              | Mode asynchrone                                                                                                   |
| ----------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| Génération d'images     | Renvoie le résultat de façon synchrone | Passer `async: true` dans le corps de la requête renvoie immédiatement un `task_id`                               |
| Génération vidéo        | Toujours asynchrone                    | Renvoie un `task_id` après la création ; le résultat s'obtient via l'interface des tâches                         |
| Génération de texte LLM | Retour synchrone ou en streaming       | Si le client s'interrompt et que les conditions sont réunies, la réponse finale est enregistrée comme tâche `llm` |

Un appel synchrone renvoie le résultat dans une seule réponse HTTP, et le résultat ne peut plus être récupéré après une coupure de connexion. Une tâche asynchrone conserve le résultat côté plateforme : le `task_id` permet de l'interroger et de le télécharger à nouveau avec la même clé API avant expiration du résultat. Ce mode convient aux requêtes de génération longues, ainsi qu'aux sorties de texte longues dont la réponse finale doit rester récupérable après une interruption.

***

<h2 id="api-overview">
  Vue d'ensemble des interfaces
</h2>

| Opération                       | Méthode | Chemin                                       | Description                                                 |
| ------------------------------- | ------- | -------------------------------------------- | ----------------------------------------------------------- |
| Créer une image asynchrone      | POST    | `/ai/v1/images/generations`                  | Ajouter `async: true` au corps de la requête                |
| Créer une vidéo asynchrone      | POST    | `/ai/v1/videos`                              | Les tâches vidéo sont asynchrones par défaut                |
| Lister les tâches               | GET     | `/ai/v1/tasks`                               | Rechercher les tâches créées par la clé API courante        |
| Consulter le détail d'une tâche | GET     | `/ai/v1/tasks/{task_id}`                     | Interroger le statut unifié et les sorties de la tâche      |
| Récupérer un résultat unique    | GET     | `/ai/v1/tasks/{task_id}/content`             | Pour les tâches à un seul fichier produit ou les tâches LLM |
| Récupérer un résultat désigné   | GET     | `/ai/v1/tasks/{task_id}/content/{result_id}` | Pour les tâches à plusieurs fichiers produits               |

Base URL : `https://aihubmix.com`, avec une authentification par Bearer Token :

```bash theme={null}
Authorization: Bearer $AIHUBMIX_API_KEY
```

<Note>
  `/ai/v1/tasks` est un point d'entrée d'interrogation unifié en lecture seule ; `POST /ai/v1/tasks` n'est pas proposé. Les images et les vidéos se créent via leur interface de génération respective. Les requêtes qui remplissent les conditions de la [reprise après interruption LLM](#llm-interruption-recovery) sont automatiquement enregistrées comme tâches `llm` après une interruption du client.
</Note>

***

<h2 id="supported-models">
  Modèles pris en charge
</h2>

Les tâches asynchrones définissent leur périmètre de prise en charge par type de tâche, sans paramètre supplémentaire à l'appel.

<h3 id="supported-models-image">
  Image asynchrone
</h3>

| Modèle           |
| ---------------- |
| `qwen-image-2.0` |

<h3 id="supported-models-video">
  Vidéo asynchrone
</h3>

| Modèle       |
| ------------ |
| `wan2.6-t2v` |

<h3 id="supported-models-llm">
  Reprise après interruption LLM
</h3>

| Modèle           |
| ---------------- |
| `gpt-5.5-pro`    |
| `claude-fable-5` |

La liste des modèles pris en charge continue de s'étendre, et ce tableau est mis à jour en conséquence.

***

<h2 id="create-async-task">
  Comment créer une tâche asynchrone
</h2>

<h3 id="create-async-image">
  Image asynchrone
</h3>

L'interface d'images renvoie le résultat de façon synchrone par défaut. Lorsque `async` vaut `true`, l'interface renvoie immédiatement l'objet tâche et la génération se poursuit en arrière-plan.

```bash theme={null}
curl -X POST https://aihubmix.com/ai/v1/images/generations \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen-image-2.0",
    "prompt": "A flower shop with delicate windows, warm sunlight streaming in",
    "n": 2,
    "size": "1024x1024",
    "async": true
  }'
```

`async` doit être un booléen. S'il est absent ou défini à `false`, l'interface d'images conserve son comportement synchrone.

<h3 id="create-async-video">
  Vidéo asynchrone
</h3>

L'interface vidéo est toujours asynchrone. Après une création réussie, elle renvoie le statut `pending` ou `in_progress` ; le passage en attente synchrone via `Prefer: wait` n'est pas pris en charge.

```bash theme={null}
curl -X POST https://aihubmix.com/ai/v1/videos \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "wan2.6-t2v",
    "prompt": "Ocean waves crashing on rocky cliffs at sunset",
    "seconds": "5",
    "size": "1280x720"
  }'
```

<h3 id="common-parameters">
  Paramètres communs
</h3>

Dans les exemples, `model`, `prompt`, `n`, `seconds` et `size` sont des paramètres de modèle courants. Les champs et valeurs pris en charge dépendent de chaque modèle et font foi dans sa documentation API ; pour les modèles vidéo, voir la [documentation de génération vidéo](/fr/api/Video-Gen). Le tableau ci-dessous décrit uniquement les paramètres communs à toutes les tâches asynchrones.

| Paramètre               | Type      | Obligatoire                                | Description                                                                  |
| ----------------------- | --------- | ------------------------------------------ | ---------------------------------------------------------------------------- |
| `async`                 | boolean   | Image : oui ; vidéo : inutile de le passer | L'interface d'images s'exécute en asynchrone lorsqu'il vaut `true`           |
| `webhook_url`           | string    | Non                                        | Adresse de rappel HTTPS de la tâche courante, 512 caractères maximum         |
| `webhook_events_filter` | string\[] | Non                                        | Statuts finaux à notifier, au choix parmi `completed`, `failed`, `cancelled` |

<Note>
  Les tâches d'image ne peuvent utiliser un Webhook que si `async: true`. Si `webhook_events_filter` est omis, la plateforme notifie les trois statuts finaux `completed`, `failed` et `cancelled`. Lorsqu'il est fourni, il doit être utilisé avec `webhook_url`, et il ne peut être ni vide ni contenir de doublons.
</Note>

***

<h2 id="llm-interruption-recovery">
  Comment fonctionne la reprise après interruption LLM
</h2>

La reprise après interruption LLM sert à récupérer la réponse finale après la déconnexion du client. Cette capacité réutilise le mode d'appel LLM existant : le comportement en streaming et le format de réponse restent inchangés, aucune interface de création supplémentaire n'est nécessaire et aucun `task_id` n'est renvoyé à l'avance.

<h3 id="recovery-conditions">
  Conditions d'activation
</h3>

Les conditions suivantes doivent être remplies simultanément :

| Condition                                                       | Description                                                                                           |
| --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| Le compte a activé les tâches asynchrones                       | Activation pour le compte courant dans la console AIHubMix                                            |
| Le modèle utilisé prend en charge la reprise après interruption | Voir [Reprise après interruption LLM](#supported-models-llm), sans paramètre supplémentaire à l'appel |
| L'appel utilise une interface LLM prise en charge               | La requête cible l'une des interfaces de génération de texte listées ci-dessous                       |
| Le client s'est interrompu                                      | Annulation par le client, coupure réseau ou annulation de la requête par l'appelant                   |

Interfaces prises en charge :

| Interface                                          | Description                                             |
| -------------------------------------------------- | ------------------------------------------------------- |
| `POST /v1/chat/completions`                        | OpenAI Chat Completions, en streaming et hors streaming |
| `POST /v1/messages`                                | Anthropic Messages, en streaming et hors streaming      |
| `POST /v1/responses`                               | OpenAI Responses API                                    |
| Gemini `generateContent` / `streamGenerateContent` | Interfaces natives de génération de texte Gemini        |

<Note>
  Aucun champ supplémentaire n'est à passer lors de l'appel. La liste des modèles pris en charge figure en [Reprise après interruption LLM](#supported-models-llm). Pour un modèle absent de ce tableau, validez la reprise après interruption avec une requête à faible coût avant la mise en production ; cette requête de validation reste facturée normalement. Si l'une des conditions n'est pas remplie, la requête s'exécute quand même normalement et aucune tâche `llm` n'est créée après l'interruption du client.
</Note>

<h3 id="recovery-flow">
  Déroulement après une interruption
</h3>

```text theme={null}
1. Le client envoie normalement une requête LLM
2. Le client se déconnecte ou annule avant la fin de la réponse
3. AIHubMix poursuit le traitement de la requête, qui reste facturée normalement
4. La réponse finale JSON ou SSE est enregistrée comme tâche de type llm
5. Interrogez la liste des tâches avec la clé API d'origine et lisez la réponse enregistrée
```

Les requêtes LLM qui se terminent normalement et dont la réponse est bien remise au client ne créent aucune tâche et n'apparaissent pas dans la liste des tâches. Une requête interrompue apparaît dans la liste une fois la réponse finale enregistrée ; elle peut donc rester temporairement introuvable pendant le traitement.

<h3 id="locate-interrupted-request">
  Retrouver la requête interrompue correspondante
</h3>

Les réponses LLM renvoient l'en-tête `X-Aihubmix-Request-Id`. Le client doit enregistrer cette valeur dès la réception des en-têtes. Après une interruption, cet identifiant de requête permet de retrouver la tâche correspondante dans la liste des tâches asynchrones de la console AIHubMix.

L'API publique des tâches ne permet pas actuellement de filtrer par identifiant de requête. Si l'identifiant n'a pas été enregistré, la recherche s'effectue par modèle et date de création, avec la même clé API que celle utilisée pour créer la requête :

```bash theme={null}
# Interroger les tâches d'interruption LLM les plus récentes
curl "https://aihubmix.com/ai/v1/tasks?object=llm&model={model}&order=desc&limit=20" \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY"

# Une fois le task_id trouvé, consulter le détail et récupérer la réponse d'origine
curl https://aihubmix.com/ai/v1/tasks/{task_id} \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY"

curl https://aihubmix.com/ai/v1/tasks/{task_id}/content \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY"
```

<Warning>
  Lorsqu'une même clé API envoie plusieurs requêtes concurrentes vers le même modèle, le modèle et la date de création ne suffisent pas à garantir une correspondance exacte. Pour une reprise fiable, enregistrez `X-Aihubmix-Request-Id` et effectuez la recherche depuis la console. Si les en-têtes de réponse n'ont pas été obtenus, évitez de considérer directement la tâche la plus récente de la liste comme celle de la requête concernée.
</Warning>

<Warning>
  Les tâches de reprise après interruption LLM n'envoient pas de Webhook pour le moment ; consultez le résultat via la liste des tâches. Une interruption du client n'arrête pas le traitement de la requête par la plateforme, et cet appel reste facturé selon les règles de l'interface LLM d'origine.
</Warning>

***

<h2 id="task-object">
  Objet tâche et statuts
</h2>

Toutes les tâches utilisent une structure de réponse unifiée :

```json theme={null}
{
  "id": "task_01K0ABCDEF",
  "object": "video",
  "model": "wan2.6-t2v",
  "status": "completed",
  "output": [
    {
      "index": 0,
      "result_id": "result_01K0XYZ",
      "type": "file",
      "content_type": "video/mp4",
      "content_url": "https://aihubmix.com/ai/v1/tasks/task_01K0ABCDEF/content"
    }
  ],
  "error": null,
  "created_at": 1784707200,
  "completed_at": 1784707320,
  "expires_at": 1784709120
}
```

| Champ          | Type         | Description                                                                         |
| -------------- | ------------ | ----------------------------------------------------------------------------------- |
| `id`           | string       | ID de tâche de la plateforme, soit le `task_id` utilisé dans les requêtes suivantes |
| `object`       | string       | Type de tâche : `llm`, `image` ou `video`                                           |
| `model`        | string       | Modèle utilisé lors de la création de la tâche                                      |
| `status`       | string       | Statut unifié de la tâche                                                           |
| `output`       | array        | Résultats récupérables ; tableau vide lorsque la tâche n'a produit aucun résultat   |
| `error`        | object/null  | Informations d'échec, contenant généralement `code` et `message`                    |
| `created_at`   | integer      | Date de création, en secondes Unix                                                  |
| `completed_at` | integer/null | Date de fin, d'échec ou d'annulation de la tâche, en secondes Unix                  |
| `expires_at`   | integer/null | Date d'expiration du premier résultat à expirer, en secondes Unix                   |

Champs des résultats contenus dans `output` :

| Champ          | Description                                                                                             |
| -------------- | ------------------------------------------------------------------------------------------------------- |
| `index`        | Rang du résultat dans la tâche courante, à partir de 0                                                  |
| `result_id`    | ID du résultat ; utilisé pour télécharger un résultat désigné d'une tâche à plusieurs fichiers produits |
| `type`         | Type de résultat : `file` pour un fichier, `response` pour une réponse LLM                              |
| `content_type` | Type de fichier du résultat (MIME), par exemple `video/mp4` ou `application/json`                       |
| `content_url`  | Adresse de téléchargement du résultat ; l'accès requiert la clé API ayant créé la tâche                 |
| `b64_json`     | Résultat encodé en Base64, que certains modèles d'image peuvent renvoyer directement                    |
| `truncated`    | Indique si la réponse LLM a été tronquée en raison de la limite de taille                               |

<h3 id="task-status">
  Description des statuts
</h3>

| Statut        | Terminé | Description                                              |
| ------------- | ------- | -------------------------------------------------------- |
| `pending`     | Non     | La plateforme a reçu la tâche, qui attend son exécution  |
| `in_progress` | Non     | La tâche est en cours d'exécution                        |
| `completed`   | Oui     | Tâche terminée, le résultat est disponible dans `output` |
| `failed`      | Oui     | Tâche en échec, la cause figure dans `error`             |
| `cancelled`   | Oui     | Tâche annulée                                            |

Il est recommandé d'interroger toutes les **15 secondes**, jusqu'à ce que le statut passe à `completed`, `failed` ou `cancelled`.

<Note>
  Une tâche `failed` ou `cancelled` peut également contenir des résultats partiels déjà générés. Pour savoir s'il existe un résultat, vérifiez aussi si `output` est vide, en plus du statut.
</Note>

***

<h2 id="query-tasks">
  Comment interroger les tâches
</h2>

<h3 id="query-task-detail">
  Consulter le détail d'une tâche
</h3>

```bash theme={null}
curl https://aihubmix.com/ai/v1/tasks/{task_id} \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY"
```

Cette interface renvoie les informations de tâche les plus récentes au moment de l'interrogation. L'interrogation ne modifie pas la tâche ; le statut est mis à jour automatiquement par la plateforme.

<h3 id="query-task-list">
  Lister les tâches
</h3>

Si la réponse de création a été perdue, ou pour consulter par lot l'historique des tâches, l'interface de liste permet de retrouver le `task_id` :

```bash theme={null}
curl "https://aihubmix.com/ai/v1/tasks?object=video&status=in_progress&limit=20&order=desc" \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY"
```

| Paramètre | Type    | Valeur par défaut | Description                                                            |
| --------- | ------- | ----------------- | ---------------------------------------------------------------------- |
| `object`  | string  | -                 | Filtre par type : `llm`, `image`, `video`                              |
| `status`  | string  | -                 | Filtre par statut unifié de tâche                                      |
| `model`   | string  | -                 | Filtre exact par nom de modèle                                         |
| `after`   | string  | -                 | Curseur de pagination, reprendre le `next_after` de la page précédente |
| `limit`   | integer | `20`              | Nombre d'éléments par page, plage de 1 à 100                           |
| `order`   | string  | `desc`            | `asc` ou `desc`                                                        |

Exemple de réponse :

```json theme={null}
{
  "object": "list",
  "data": [
    {
      "id": "task_01K0ABCDEF",
      "object": "video",
      "model": "wan2.6-t2v",
      "status": "in_progress",
      "output": [],
      "error": null,
      "created_at": 1784707200,
      "completed_at": null,
      "expires_at": null
    }
  ],
  "has_more": true,
  "next_after": "task_01K0ABCDEF"
}
```

| Champ        | Description                                                                    |
| ------------ | ------------------------------------------------------------------------------ |
| `object`     | Toujours `list`, indique une réponse de type liste                             |
| `data`       | Tableau des tâches de la page courante                                         |
| `has_more`   | Indique s'il existe une page suivante                                          |
| `next_after` | Curseur de la page suivante ; renvoyé uniquement s'il existe une page suivante |

Requête de la page suivante :

```bash theme={null}
curl "https://aihubmix.com/ai/v1/tasks?limit=20&order=desc&after=task_01K0ABCDEF" \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY"
```

***

<h2 id="get-task-results">
  Comment récupérer les résultats d'une tâche
</h2>

<h3 id="single-artifact">
  Tâche à un seul fichier produit
</h3>

Lorsque `output` ne contient qu'un seul fichier, l'accès est direct :

```bash theme={null}
curl https://aihubmix.com/ai/v1/tasks/{task_id}/content \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  --output result.bin
```

Il est également possible d'utiliser directement `output[0].content_url`. Le `Content-Type` de la réponse de téléchargement correspond à `output[0].content_type`.

<h3 id="multiple-artifacts">
  Tâche à plusieurs fichiers produits
</h3>

Lorsque `output` contient plusieurs fichiers, le `result_id` correspondant doit être précisé :

```bash theme={null}
curl https://aihubmix.com/ai/v1/tasks/{task_id}/content/{result_id} \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  --output result.png
```

Si le `result_id` n'est pas précisé pour une tâche à plusieurs fichiers produits, l'interface renvoie `400 result_id_required`.

<h3 id="llm-response-task">
  Tâche de réponse LLM
</h3>

Lorsque les conditions de la [reprise après interruption LLM](#llm-interruption-recovery) sont remplies et que la réponse a été enregistrée, l'`object` de la tâche vaut `llm` et le `type` de l'élément d'`output` vaut `response`. Le type de contenu peut être :

* `application/json` : réponse JSON standard
* `text/event-stream` : réponse en streaming SSE enregistrée

```bash theme={null}
curl https://aihubmix.com/ai/v1/tasks/{task_id}/content \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY"
```

L'indicateur de troncature se trouve dans `output[0].truncated` du détail de la tâche. La valeur `true` signifie que la réponse enregistrée a été tronquée en raison de la limite de taille. `GET /ai/v1/tasks/{task_id}/content` renvoie le contenu JSON ou SSE d'origine, sans champ `truncated` ajouté autour du contenu ; il convient donc de consulter d'abord le détail de la tâche, puis de lire le contenu.

<Warning>
  Les résultats peuvent expirer, et un nombre maximal de téléchargements peut s'appliquer. Enregistrez-les à temps avant `expires_at`. Un résultat expiré renvoie `410 artifact_expired` ; le dépassement de la limite de téléchargements renvoie `429 too_many_downloads`.
</Warning>

***

<h2 id="webhooks">
  Comment utiliser les Webhooks
</h2>

Un Webhook au niveau de la tâche peut actuellement être fourni lors de la création d'une tâche asynchrone. Pour être notifié par AIHubMix une fois la tâche terminée, passez `webhook_url` et éventuellement `webhook_events_filter` dans le corps de la requête d'image ou de vidéo asynchrone :

```bash theme={null}
curl -X POST https://aihubmix.com/ai/v1/videos \
  -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "wan2.6-t2v",
    "prompt": "A tranquil Japanese garden at sunrise",
    "seconds": "5",
    "webhook_url": "https://example.com/webhooks/aihubmix",
    "webhook_events_filter": ["completed", "failed"]
  }'
```

L'adresse de rappel doit utiliser HTTPS et ne peut pas pointer vers la machine locale, un réseau privé ou une autre adresse restreinte.

<h3 id="webhook-payload">
  Requête de rappel
</h3>

AIHubMix envoie une requête `POST` à l'adresse de rappel :

```json theme={null}
{
  "event_id": "evt_01K0ABCDEF",
  "event_type": "completed",
  "created_at": "2026-07-22T12:00:00Z",
  "data": {
    "task_id": "task_01K0ABCDEF",
    "status": "completed",
    "model": "wan2.6-t2v",
    "results": [
      {
        "url": "https://aihubmix.com/ai/v1/tasks/task_01K0ABCDEF/content"
      }
    ]
  }
}
```

| Champ                | Description                                                                             |
| -------------------- | --------------------------------------------------------------------------------------- |
| `event_id`           | ID unique de l'événement de rappel, utilisé pour identifier les notifications en double |
| `event_type`         | Statut final de la tâche : `completed`, `failed` ou `cancelled`                         |
| `created_at`         | Date de création de l'événement de rappel                                               |
| `data.task_id`       | ID de la tâche, utilisable pour consulter son détail                                    |
| `data.status`        | Statut actuel de la tâche                                                               |
| `data.model`         | Modèle utilisé lors de la création de la tâche                                          |
| `data.results[].url` | Adresse de téléchargement des résultats générés                                         |
| `data.error.code`    | Code d'erreur, présent uniquement pour les événements d'échec                           |
| `data.error.message` | Cause de l'échec, présente uniquement pour les événements d'échec                       |

Les URL de `results` requièrent toujours la clé API ayant créé la tâche pour y accéder.

<h3 id="webhook-retry">
  Nouvelles tentatives et déduplication
</h3>

La plateforme tente au moins une livraison du rappel, un même événement peut donc être envoyé plusieurs fois :

* HTTP `2xx` indique une réception réussie.
* HTTP `5xx`, une erreur réseau ou un dépassement de délai déclenchent une nouvelle tentative.
* HTTP `3xx` et `4xx` ne déclenchent pas de nouvelle tentative.
* 6 livraisons au maximum, avec des intervalles successifs de 1, 4, 16, 64 et 256 secondes.

Le destinataire doit enregistrer `event_id`. À la réception d'un `event_id` déjà connu, ignorez le traitement métier et renvoyez directement `2xx`.

<Warning>
  Le Webhook au niveau de la tâche ne fournit pas actuellement d'identifiant de signature dédié et configurable. Après réception d'une notification, appelez `GET /ai/v1/tasks/{task_id}` avec la clé API ayant créé la tâche et considérez le résultat de cette interrogation comme faisant foi.
</Warning>

***

<h2 id="error-codes">
  Réponses d'erreur et codes d'erreur
</h2>

Les réponses d'erreur utilisent une structure unifiée :

```json theme={null}
{
  "error": {
    "message": "Task not found.",
    "type": "invalid_request_error",
    "code": "task_not_found",
    "tid": "req_01K0..."
  }
}
```

| Champ           | Description                                                                                   |
| --------------- | --------------------------------------------------------------------------------------------- |
| `error.message` | Cause de l'erreur                                                                             |
| `error.type`    | Type d'erreur                                                                                 |
| `error.code`    | Code d'erreur exploitable par programme                                                       |
| `error.tid`     | ID de traçage de la requête ; à fournir lors d'une demande de diagnostic au support technique |

| Code HTTP | Code d'erreur                   | Description                                                                   |
| --------- | ------------------------------- | ----------------------------------------------------------------------------- |
| 400       | `invalid_request`               | Type ou valeur de paramètre incorrect                                         |
| 400       | `result_id_required`            | `result_id` non précisé pour une tâche à plusieurs fichiers produits          |
| 400       | `webhook_invalid`               | URL de Webhook non valide                                                     |
| 400       | `webhook_events_filter_invalid` | Liste d'événements Webhook non valide                                         |
| 401       | `authentication_failed`         | Clé API absente ou non valide                                                 |
| 403       | `async_not_enabled`             | Tâches asynchrones non activées pour le compte                                |
| 404       | `task_not_found`                | Tâche inexistante, ou n'appartenant pas à la clé API courante                 |
| 404       | `result_not_found`              | Résultat inexistant ou actuellement indisponible                              |
| 410       | `artifact_expired`              | Résultat expiré                                                               |
| 429       | `too_many_downloads`            | Limite de téléchargements du résultat dépassée                                |
| 503       | `async_unavailable`             | Service d'images asynchrones temporairement indisponible, réessayez plus tard |

***

<h2 id="full-example">
  Exemple complet
</h2>

Processus complet de création d'une tâche vidéo, d'interrogation par polling et de téléchargement de tous les résultats :

<CodeGroup>
  ```python Python theme={null}
  import base64
  import os
  import time

  import requests

  BASE_URL = "https://aihubmix.com"
  API_KEY = os.environ["AIHUBMIX_API_KEY"]
  HEADERS = {
      "Authorization": f"Bearer {API_KEY}",
      "Content-Type": "application/json",
  }

  # 1. Créer la tâche
  response = requests.post(
      f"{BASE_URL}/ai/v1/videos",
      headers=HEADERS,
      json={
          "model": "wan2.6-t2v",
          "prompt": "A cat playing jazz on a piano",
          "seconds": "5",
          "size": "1280x720",
      },
      timeout=60,
  )
  response.raise_for_status()
  task = response.json()
  task_id = task["id"]

  # 2. Interroger jusqu'à ce que la tâche soit terminée, en échec ou annulée
  while task["status"] not in {"completed", "failed", "cancelled"}:
      time.sleep(15)
      response = requests.get(
          f"{BASE_URL}/ai/v1/tasks/{task_id}",
          headers=HEADERS,
          timeout=30,
      )
      response.raise_for_status()
      task = response.json()
      print("status:", task["status"])

  # 3. Récupérer les résultats
  if task["output"]:
      for index, item in enumerate(task["output"]):
          if encoded := item.get("b64_json"):
              with open(f"result-{index}.bin", "wb") as file:
                  file.write(base64.b64decode(encoded))
              continue
          result = requests.get(
              item["content_url"],
              headers=HEADERS,
              timeout=120,
          )
          result.raise_for_status()
          with open(f"result-{index}.bin", "wb") as file:
              file.write(result.content)
  elif task["status"] == "failed":
      raise RuntimeError(task.get("error"))
  ```

  ```typescript TypeScript theme={null}
  import { writeFile } from "node:fs/promises";

  const BASE_URL = "https://aihubmix.com";
  const HEADERS = {
    Authorization: `Bearer ${process.env.AIHUBMIX_API_KEY}`,
    "Content-Type": "application/json",
  };

  // 1. Créer la tâche
  const created = await fetch(`${BASE_URL}/ai/v1/videos`, {
    method: "POST",
    headers: HEADERS,
    body: JSON.stringify({
      model: "wan2.6-t2v",
      prompt: "A cat playing jazz on a piano",
      seconds: "5",
      size: "1280x720",
    }),
  });
  let task = await created.json();

  // 2. Interroger jusqu'à ce que la tâche soit terminée, en échec ou annulée
  const finished = new Set(["completed", "failed", "cancelled"]);
  while (!finished.has(task.status)) {
    await new Promise((resolve) => setTimeout(resolve, 15_000));
    const polled = await fetch(`${BASE_URL}/ai/v1/tasks/${task.id}`, {
      headers: HEADERS,
    });
    task = await polled.json();
    console.log("status:", task.status);
  }

  // 3. Récupérer les résultats
  if (task.output?.length) {
    for (const [index, item] of task.output.entries()) {
      if (item.b64_json) {
        await writeFile(`result-${index}.bin`, Buffer.from(item.b64_json, "base64"));
        continue;
      }
      const result = await fetch(item.content_url, { headers: HEADERS });
      await writeFile(`result-${index}.bin`, Buffer.from(await result.arrayBuffer()));
    }
  } else if (task.status === "failed") {
    throw new Error(JSON.stringify(task.error));
  }
  ```

  ```shell curl theme={null}
  # 1. Créer la tâche et noter l'id renvoyé
  curl -X POST https://aihubmix.com/ai/v1/videos \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "wan2.6-t2v",
      "prompt": "A cat playing jazz on a piano",
      "seconds": "5",
      "size": "1280x720"
    }'

  # 2. Interroger le statut toutes les 15 secondes
  curl https://aihubmix.com/ai/v1/tasks/task_01K0ABCDEF \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY"

  # 3. Télécharger le résultat une fois le statut passé à completed
  curl https://aihubmix.com/ai/v1/tasks/task_01K0ABCDEF/content \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
    --output result.mp4
  ```
</CodeGroup>

***

<h2 id="faq">
  Questions fréquentes
</h2>

**À quelle fréquence interroger le statut d'une tâche ?**

Il est recommandé d'interroger toutes les 15 secondes, afin d'éviter un polling à haute fréquence. Même avec un Webhook, conservez une interrogation à basse fréquence en secours.

**Comment retrouver une tâche après la perte de la réponse de création ?**

Appelez `GET /ai/v1/tasks` avec la même clé API que celle ayant créé la tâche. Les filtres `object`, `model` et `status` permettent de restreindre la recherche.

**Pourquoi une autre clé API du même compte ne trouve-t-elle pas la tâche ?**

Les tâches sont isolées par clé API. Les requêtes d'interrogation, de téléchargement et de liste doivent toutes utiliser la clé ayant servi à créer la tâche.

**Pourquoi `output` n'est-il pas un tableau vide alors que la tâche a échoué ?**

Certains modèles peuvent avoir généré des résultats exploitables avant l'échec ou l'annulation globale de la tâche. Dès qu'`output` contient `content_url` ou `b64_json`, le résultat peut être récupéré par la méthode correspondante.

**Que faire si le Webhook n'est pas reçu ?**

Vérifiez que l'adresse de rappel est accessible publiquement, qu'elle utilise HTTPS et qu'elle renvoie `2xx` en moins de 10 secondes. Avec ou sans Webhook, le statut final reste consultable via `GET /ai/v1/tasks/{task_id}`.

**La reprise après interruption LLM impose-t-elle de modifier le code existant ?**

Non. Le mode d'appel, le comportement en streaming et le format de réponse restent inchangés. Il est recommandé d'enregistrer l'en-tête de réponse `X-Aihubmix-Request-Id`, afin de localiser précisément la tâche correspondante dans la console après une interruption.

***

Date de mise à jour : 2026-07-28
