Tutoriel
Vous ne recevez pas les callbacks HiAPI ? Guide de diagnostic et de résolution des problèmes de livraison Webhook
Lorsque vous soumettez une tâche à POST https://api.hiapi.ai/v1/tasks, vous avez inclus callback.url pour que HiAPI vous notifie par POST une fois la tâche terminée. Pourtant, alors que la tâche est déjà success dans GET /v1/tasks/{taskId}, votre interface de callback ne reçoit rien du tout. Dans huit cas sur dix, le problème ne vient pas de HiAPI, mais de l'accessibilité de l'adresse de callback, du fait que le récepteur ne renvoie pas de 2xx comme convenu, ou d'une course entre le polling et le callback. Voici un passage en revue point par point selon le véritable contrat de callback, avec des étapes de correction applicables immédiatement.
Si votre tâche n'atteint jamais l'état terminal (
data.statusreste longtemps surqueued/handling/archiving), il s'agit d'un autre type de problème ; consultez le guide de diagnostic et de nouvelle tentative pour les tâches HiAPI bloquées ou expirées. Cet article ne traite que du cas où la tâche est déjà terminée mais où la notification de callback ne parvient pas.
Symptômes
Le schéma typique : tout va bien côté tâche, GET /v1/tasks/{taskId} renvoie data.status à success (ou fail), mais les journaux de votre interface de callback déployée sur l'Internet public ne contiennent aucune requête POST provenant de HiAPI ; ou bien vous en recevez parfois, mais souvent pas ; ou encore le même taskId est livré deux fois, ce que votre logique de déduplication considère comme une anomalie.
Partez d'un fait : le callback n'est qu'un moyen parmi d'autres de récupérer le résultat, pas le seul canal. Les tâches asynchrones de HiAPI peuvent toujours être récupérées à l'état terminal par un polling actif via GET /v1/tasks/{taskId} ; le callback (Webhook) ne sert qu'à vous éviter le polling. Donc « callback non reçu » ne signifie pas « résultat inaccessible » : commencez par confirmer avec le polling que la tâche elle-même est en bon état, puis localisez le problème de livraison.
Le véritable contrat de callback (à aligner avant de déboguer)
Lors de l'enregistrement du callback, callback est un champ de premier niveau de POST /v1/tasks, au même niveau que model et input ; il ne doit pas être placé dans input :
{
"model": "gpt-image-2",
"input": { "prompt": "a calm blue data center" },
"callback": {
"url": "https://your-domain.com/hiapi/callback",
"when": "final"
}
}
Quelques points à retenir impérativement :
callback.urldoit être une URL http(s) accessible depuis l'Internet public ; HiAPI y envoie une requête POST depuis le réseau public.callback.whenn'accepte actuellement quefinal: une livraison lorsque la tâche atteint l'état terminal,successetfaildéclenchent tous deux l'envoi. Il n'existe pas de callback par progression ou par étapes.- Le mode de livraison est
POST+Content-Type: application/json, et le corps de la requête est identique au champdatadeGET /v1/tasks/{taskId}, c'est-à-dire l'objet de détail de la tâche, contenantstatus,output,error,taskId,created,completed, etc. - En cas d'échec de livraison (non-2xx / timeout / erreur réseau), nouvelle tentative selon immédiat → +1 minute → +5 minutes → +20 minutes, au maximum 4 fois ; après 4 échecs, aucune nouvelle tentative n'est effectuée, et cela n'affecte pas l'état de la tâche elle-même.
- Le callback d'état terminal a une sémantique **au moins une fois (at least once)**, et non exactement une fois. Le même
taskIdpeut être livré plusieurs fois ; le récepteur doit effectuer une déduplication idempotente basée surtaskId.
Les détails du contrat font foi dans la documentation officielle : création de tâche et champ callback, vue d'ensemble de l'API asynchrone (nouvelles tentatives de callback et idempotence).
Causes fréquentes (classées par probabilité)
1. L'adresse de callback n'est pas accessible depuis l'Internet public (la plus fréquente)
Vous avez indiqué http://localhost:3000/..., une IP interne, ou un domaine résolu uniquement par le DNS interne. HiAPI ne peut pas atteindre votre machine locale depuis le réseau public, donc la livraison échoue forcément. C'est l'erreur la plus courante en développement local.
2. Le récepteur ne renvoie pas de 2xx
Le handler lève une exception, renvoie une redirection 3xx, est bloqué en 401/403 par un middleware d'authentification, ou renvoie un 5xx. HiAPI ne considère comme réussie qu'une réponse HTTP 2xx ; tout le reste déclenche une nouvelle tentative, et une fois la fenêtre de nouvelles tentatives épuisée, cela se manifeste par « rien reçu ».
3. Délai de traitement dépassé
Le handler effectue d'abord des opérations lourdes (téléchargement du produit, transfert vers le stockage objet, écriture en base de données, envoi de messages) avant de renvoyer 200 ; le délai est jugé dépassé et déclenche une nouvelle tentative, ce qui, cumulé, ressemble à une perte de paquets.
4. callback placé dans input
C'est un champ de premier niveau ; placé dans input, il n'est pas reconnu comme un enregistrement de callback ; de plus, le schéma input de chaque modèle est strict, et l'ajout d'une clé inconnue provoque généralement une erreur synchrone à la soumission : invalid input: <root>: additional properties 'callback' not allowed ; la tâche n'a alors pas du tout été soumise avec succès.
5. when renseigné avec une valeur autre que final
Seul final est actuellement pris en charge ; toute autre valeur est rejetée.
6. Course entre polling et callback
Vous avez activé à la fois le polling et l'attente du callback ; le polling obtient l'état terminal en premier et ferme l'enregistrement local de la tâche ; à l'arrivée du callback, aucun enregistrement correspondant n'est trouvé, et cela est considéré comme « non reçu ».
7. Interception par certificat ou WAF
L'adresse de callback utilise un certificat auto-signé / expiré, ou le WAF bloque comme trafic suspect un POST anonyme sans User-Agent habituel et sans votre en-tête d'authentification maison.
Étapes de correction
- Confirmez d'abord que la tâche elle-même est en bon état. Utilisez
GET /v1/tasks/{taskId}pour vérifierdata.status; si c'estsuccess/fail, la tâche est à l'état terminal et le problème se situe au niveau de la livraison ; si elle reste dans un état non terminal, il s'agit d'un autre type de problème (voir le diagnostic de blocage en début d'article). - Remplacez l'adresse de callback par un domaine https accessible publiquement. Depuis une machine externe, exécutez
curl -i -X POST https://your-domain.com/hiapi/callback -d '{}'pour vérifier la connectivité et l'obtention d'un 2xx. Pour le débogage en localhost, utilisez un tunnel public pour exposer votre port local. - Enregistrez d'abord le callback de manière fiable, puis renvoyez rapidement un 2xx. À la réception de la requête, écrivez d'abord le contenu du callback dans la base de données ou une file persistante (cette étape doit être rapide), puis renvoyez un 2xx après succès de l'écriture ; placez les opérations lourdes comme le téléchargement et le transfert en arrière-plan asynchrone. Ne renvoyez pas 200 avant l'écriture en base : si le processus plante ensuite, ce callback est perdu, et HiAPI ne le renverra plus après avoir reçu un 2xx. Exemptez également ce chemin du middleware d'authentification, car le callback de HiAPI ne porte pas vos en-têtes d'authentification maison.
- Vérifiez la position et la valeur de
callback. Confirmez qu'il est au premier niveau du corps de la requête (au même niveau quemodeletinput), queurlest une URL http(s) publique et quewhenvautfinal. - Effectuez une déduplication idempotente basée sur
taskId. À la réception du callback, vérifiez d'abord si cetaskIda déjà été traité localement ; s'il ne l'a pas été, écrivez-le en base / déclenchez les actions suivantes ; avec la sémantique at-least-once, une arrivée en double est normale, ne la rejetez pas comme une anomalie. - Ajoutez un polling de secours. Pour les
taskIddont le callback n'est pas reçu au-delà de la durée attendue, effectuez activementGET /v1/tasks/{taskId}pour récupérer l'état terminal. Le callback est une optimisation, le polling est la garantie minimale ; les deux doivent converger vers la même logique d'idempotence. - Transférez rapidement les produits. Le
output[].urldu corps du callback est un lien temporaire (storagevauttemp,expireAtest un horodatage Unix, expiration après environ 7 jours) ; téléchargez-le ou transférez-le immédiatement vers votre propre stockage, ne stockez pas directement le lien chaud.
Exemple de vérification minimal
Sans toucher au callback pour l'instant, prouvez avec « soumission + polling » que votre clé et l'intégration elle-même fonctionnent (avec un id de modèle brut) :
# 1. Soumettre la tâche
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-image-2","input":{"prompt":"a calm blue data center"}}'
# → {"code":200,"message":"success","data":{"taskId":"tk-hiapi-..."}}
# 2. Interroger l'état terminal avec le taskId renvoyé
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-xxxx \
-H "Authorization: Bearer $HIAPI_API_KEY"
# → data.status passe de queued/handling/archiving à success (avec output) ou fail (avec error)
Si la soumission renvoie HTTP 401 + {"error":{"code":"permission_denied","type":"hiapi_error","request_id":"..."}}, cela signifie que la clé API est incorrecte ; vérifiez dans la console puis réessayez. Une fois l'intégration confirmée, ajoutez le champ callback de premier niveau au corps du POST, et vérifiez point par point le récepteur selon les étapes de correction ci-dessus.
FAQ
Je ne reçois jamais le callback, mais la tâche a en fait réussi ; puis-je encore récupérer le résultat ?
Oui. À tout moment, vous pouvez faire GET /v1/tasks/{taskId} pour lire data.status et data.output ; la perte du callback ne vous empêche pas de récupérer activement le résultat.
Combien de fois le callback est-il retenté et à quel intervalle ?
En cas de non-2xx / timeout / erreur réseau, nouvelle tentative selon immédiat → +1 minute → +5 minutes → +20 minutes, au maximum 4 fois. Après 4 échecs, aucune nouvelle tentative, et cela n'affecte pas l'état success/fail de la tâche elle-même.
Est-il normal de recevoir deux callbacks pour la même tâche ?
Oui. Le callback d'état terminal a une sémantique « au moins une fois » ; effectuez simplement une déduplication idempotente basée sur taskId, ne traitez pas une livraison en double comme une erreur.
Comment recevoir les callbacks en développement local ?
HiAPI ne peut pas atteindre localhost ni les adresses internes. Soit vous utilisez un tunnel public pour mapper votre port local sur l'Internet public, soit vous utilisez directement le polling en phase locale et basculez sur les callbacks en production.
Quels champs contient le corps de la requête de callback ?
Identique au champ data de GET /v1/tasks/{taskId}, il contient taskId, status, output (tableau des produits en cas de succès), error (code et message en cas d'échec), created, completed, etc. Voir la documentation sur le détail des tâches.
Ne pas recevoir de callback entraîne-t-il une facturation supplémentaire ? Non. L'échec d'une tâche n'est pas facturé et le quota réservé est restitué ; la réussite ou non de la livraison du callback ne modifie pas le résultat de facturation de la tâche, qui dépend uniquement du fait que la tâche a finalement généré un résultat avec succès.
Articles similaires
Voir tous les articles →-
Tutoriel
Comment appeler hailuo-2.3-fast/image-to-video via l'API HiAPI : curl et Python en pratique
La première requête exploitable du palier image-vers-vidéo rapide et économique — de l'ID du modèle au téléchargement du MP4
-
Tutoriel
Comment appeler hailuo-2.3/text-to-video via l'API HiAPI : curl, Python et exemples de requêtes exécutables
-
Tutoriel
Utiliser Kandinsky 6.0 Pro texte-vers-vidéo sur HiAPI : tutoriel curl et Python
Démonstration pratique axée sur la requête : construire l'appel du prompt au clip vidéo, soumettre la requête, interroger l'état d'achèvement et télécharger le résultat