Passer au contenu principal
Lors de la soumission de tâches de génération asynchrones telles que vidéo / image / audio, vous pouvez indiquer une URL de rappel. Une fois la tâche terminée (réussie ou échouée), nous enverrons activement le résultat par POST à votre URL, pour vous éviter d’interroger en continu.

Démarrage rapide

Lors de la soumission d’une tâche, ajoutez un champ webhook au corps de la requête :
curl -X POST https://votre-domaine-d-acces/v1/images/generations \
  -H "Authorization: Bearer VOTRE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "a red apple on a table",
    "size": "1024x1024",
    "webhook": "https://your-server.com"
  }'
Une fois la tâche terminée, nous enverrons une requête POST à votre URL + /callback.
Les autres points de terminaison de tâches asynchrones (vidéo, audio, etc.) fonctionnent de la même manière : ajoutez simplement le champ webhook au corps de la requête.

Règles d’URL

Le webhook que vous fournissez est l’URL de base, à laquelle nous ajoutons automatiquement /callback :
Votre webhookOù nous envoyons réellement le POST
https://your-server.comhttps://your-server.com/callback
https://your-server.com/apihttps://your-server.com/api/callback
https://your-server.com/api/https://your-server.com/api/callback
Votre serveur doit donc disposer d’un point de terminaison acceptant POST .../callback.

Ce que vous allez recevoir

Le contenu envoyé est exactement identique à ce que renvoie le point de terminaison « Obtenir le statut d’une tâche » : vous pouvez le traiter avec la même logique d’analyse.
{
  "id": "task_01KV7FXR8BEYS1BWHJCT3JMCJ5",
  "status": "completed",
  "progress": 100,
  "created": 1781589029,
  "completed": 1781589058,
  "actual_time": 29,
  "cost": 0.006,
  "credits_cost": 0.06,
  "result": {
    "images": [{ "url": ["https://.../result.png"], "expires_at": 1781675458 }]
  }
}
Pour les tâches vidéo, le résultat se trouve dans result.videos, et pour l’audio dans result.audios.
Nous n’envoyons que lorsqu’une tâche atteint un état terminal (completed / failed) ; nous n’envoyons pas pendant le traitement.

Nouvelles tentatives et déduplication (important)

  • Nouvelles tentatives : Si votre serveur ne renvoie pas 2xx en environ 10 secondes, ou renvoie 5xx, nous réessaierons automatiquement, jusqu’à 3 fois, à des intervalles d’environ 10 s, 30 s et 60 s. Si les 3 échouent, nous abandonnons (en environ 2 minutes).
  • Pas de nouvelle tentative : Si votre point de terminaison renvoie 4xx (considéré comme une URL / requête incorrecte), nous abandonnons immédiatement sans réessayer.
  • Déduplication : Normalement, une tâche n’est envoyée qu’une seule fois. Mais dans des cas extrêmes (p. ex. un redémarrage de notre côté après l’envoi mais avant la confirmation), vous pourriez recevoir des envois en double. Veillez à dédupliquer de manière idempotente par id (task_id) pour éviter un double traitement.
Recommandations pour votre point de terminaison de réception :
1

Renvoyez 2xx le plus tôt possible

Acceptez et mettez en file d’attente d’abord, puis traitez de manière asynchrone : ne nous faites pas attendre la fin de votre traitement.
2

Dédupliquez par id

Utilisez id (task_id) comme clé d’idempotence pour éviter un double traitement.
3

Configurez et vérifiez la signature

En production, vérifiez l’origine des requêtes de rappel et rejetez les requêtes falsifiées.

Exigences pour l’URL de rappel

Pour des raisons de sécurité, l’URL de rappel doit respecter les conditions suivantes :
ExigenceDescription
Accessible publiquementNe peut pas être une adresse interne / locale (p. ex. 127.0.0.1, 10.x, 192.168.x seront rejetées)
Protocolehttp ou https (https recommandé)
PortUtilisez des ports standard (80 / 443) ; les ports non standard peuvent être bloqués
DomaineNe peut pas pointer vers notre propre domaine de service
Les URL qui ne respectent pas ces exigences sont rejetées (aucun envoi, aucune nouvelle tentative).

FAQ

Vérifiez point par point :
  1. La tâche est-elle réellement terminée ? Consultez les détails de la tâche : status est-il completed / failed (aucun envoi pendant le traitement) ?
  2. Votre URL est-elle accessible publiquement ? Pouvons-nous atteindre votre /callback ?
  3. Le port est-il un port standard (80 / 443) ? Les ports non standard peuvent être bloqués par les politiques de sécurité.
  4. Votre /callback a-t-il renvoyé 2xx à temps ? En cas de 4xx, nous abandonnons immédiatement.
  5. Utilisez-vous https ? Le certificat est-il valide ?
Certains modèles produisent plusieurs images à la fois, donc images[].url peut être un tableau : traitez-le simplement comme un tableau.
Si result contient expires_at (horodatage Unix), cela indique l’heure d’expiration du lien : transférez-le/sauvegardez-le rapidement.
Non. Nous n’envoyons qu’une seule fois, lorsque la tâche réussit ou échoue définitivement.

Exemple minimal de récepteur

Python
from http.server import BaseHTTPRequestHandler, HTTPServer
import json

class H(BaseHTTPRequestHandler):
    def do_POST(self):
        n = int(self.headers.get("Content-Length") or 0)
        body = self.rfile.read(n)
        data = json.loads(body)
        print("Rappel de tâche reçu :", data["id"], data["status"])
        # TODO : dédupliquer par id, vérifier la signature, puis traiter
        self.send_response(200); self.end_headers()
        self.wfile.write(b'{"ok":true}')

HTTPServer(("0.0.0.0", 443), H).serve_forever()
Renvoyez 200 le plus tôt possible et exécutez votre logique de traitement de manière asynchrone en arrière-plan.