Tutoriale
Non ricevi i callback di HiAPI? Guida alla diagnosi e alla risoluzione dei problemi di consegna dei Webhook
Quando invii un'attività a POST https://api.hiapi.ai/v1/tasks includendo callback.url, vuoi che HiAPI ti invii una notifica POST al termine dell'attività, ma anche se in GET /v1/tasks/{taskId} il task risulta già success, il tuo endpoint di callback non riceve nemmeno una richiesta. In questi casi il problema quasi mai risiede in HiAPI, bensì nella raggiungibilità dell'URL di callback, nella mancata risposta 2xx da parte del ricevente, oppure in un conflitto tra polling e callback. Di seguito analizziamo punto per punto il reale contratto di callback e forniamo passaggi di correzione applicabili immediatamente.
Se il tuo task non raggiunge mai lo stato finale (
data.statusresta a lungo inqueued/handling/archiving), si tratta di un altro tipo di problema: consulta la guida alla diagnosi e ai tentativi di ripetizione per attività HiAPI bloccate o in timeout. Questo articolo tratta solo lo scenario in cui il task è già terminato ma la notifica di callback non viene ricevuta.
Sintomo del problema
Il comportamento tipico è che il task è del tutto normale: GET /v1/tasks/{taskId} restituisce data.status pari a success (o fail), ma nei log del tuo endpoint di callback esposto pubblicamente non compare alcun record POST proveniente da HiAPI; oppure i callback arrivano sporadicamente e spesso si perdono; oppure lo stesso taskId viene consegnato due volte e la tua logica di deduplicazione lo interpreta come anomalia.
Stabiliamo subito un fatto: il callback è solo uno dei modi per ottenere il risultato, non l'unico canale. I task asincroni di HiAPI possono sempre essere interrogati attivamente tramite GET /v1/tasks/{taskId} per ottenere lo stato finale; il callback (Webhook) serve solo a evitarti il polling. Quindi "non ricevo il callback" non equivale a "non riesco a ottenere il risultato": prima verifica con il polling che il task stesso sia integro, poi individua il problema di consegna.
Il vero contratto di callback (allinearsi prima di risolvere)
Al momento della registrazione del callback, callback è un campo di primo livello di POST /v1/tasks, allo stesso livello di model e input, e non va inserito dentro input:
{
"model": "gpt-image-2",
"input": { "prompt": "a calm blue data center" },
"callback": {
"url": "https://your-domain.com/hiapi/callback",
"when": "final"
}
}
Alcuni punti da ricordare:
callback.urldeve essere un URL http(s) raggiungibile dalla rete pubblica; HiAPI vi invia una POST dalla rete pubblica.callback.whenattualmente accetta solofinal: viene consegnato una volta quando il task raggiunge lo stato finale, e viene attivato sia persuccessche perfail. Non esistono callback basati su avanzamento o fasi intermedie.- La modalità di consegna è
POST+Content-Type: application/json, e il corpo della richiesta è identico al campodatadiGET /v1/tasks/{taskId}, ovvero l'oggetto di dettaglio del task, che includestatus,output,error,taskId,created,completed, ecc. - In caso di fallimento della consegna (non 2xx / timeout / errore di rete), la riconsegna avviene secondo la sequenza immediata → +1 minuto → +5 minuti → +20 minuti, per un massimo di 4 tentativi; dopo 4 fallimenti non viene più ritentato e non influisce sullo stato del task stesso.
- Il callback di stato finale ha semantica at least once (almeno una volta), non exactly once. Lo stesso
taskIdpuò essere consegnato più volte; il ricevente deve effettuare una deduplicazione idempotente in base ataskId.
Per i dettagli del contratto fai riferimento alla documentazione ufficiale: creazione del task e campo callback, panoramica delle API asincrone (retry e idempotenza dei callback).
Cause comuni (ordinate per probabilità)
1. Indirizzo di callback non accessibile pubblicamente (la più comune)
È stato scritto come http://localhost:3000/..., un IP di rete interna, o un dominio che si risolve solo nella DNS interna. HiAPI non può raggiungere la tua macchina locale dalla rete pubblica e di conseguenza non riesce a consegnare. È l'errore più frequente in fase di sviluppo locale.
2. Il ricevente non restituisce 2xx
L'handler genera un'eccezione, restituisce un redirect 3xx, viene bloccato a 401/403 da un middleware di autenticazione, oppure restituisce 5xx. HiAPI considera consegna riuscita solo un HTTP 2xx; tutto il resto avvia i retry, e quando la finestra di retry si esaurisce si manifesta come "callback non ricevuto".
3. Timeout di elaborazione
Nell'handler si eseguono prima le operazioni pesanti (download del prodotto, trasferimento su object storage, scrittura su database, invio di messaggi) e solo dopo si restituisce 200; il ritardo eccessivo causa un timeout che attiva i retry, e la sovrapposizione dei tentativi sembra una perdita di pacchetti.
4. callback inserito dentro input
È un campo di primo livello; se inserito dentro input non viene riconosciuto come registrazione di callback. Inoltre lo schema di input di ciascun modello è rigoroso, e l'inserimento di chiavi sconosciute di solito genera un errore sincrono all'invio: invalid input: <root>: additional properties 'callback' not allowed; in pratica il task non è mai stato inviato con successo.
5. when impostato a un valore diverso da final
Attualmente è supportato solo final; qualsiasi altro valore viene rifiutato.
6. Conflitto tra polling e callback
Si attivano sia il polling che l'attesa del callback; il polling ottiene per primo lo stato finale e chiude il record locale del task; quando arriva il callback non trova il record corrispondente e viene interpretato come "non ricevuto".
7. Blocco da parte di certificati o WAF
L'indirizzo di callback usa un certificato self-signed / scaduto, oppure il WAF blocca come traffico sospetto le POST anonime prive di UA convenzionale e dei tuoi header di autenticazione.
Passaggi di correzione
- Verifica prima che il task stesso sia integro. Controlla
data.statusconGET /v1/tasks/{taskId}: se èsuccess/failil task è in stato finale e il problema è nella fase di consegna; se è ancora in uno stato non finale si tratta di un altro tipo di problema (vedi la diagnosi sui blocchi all'inizio dell'articolo). - Sostituisci l'indirizzo di callback con un dominio https pubblico. Da una macchina esterna esegui
curl -i -X POST https://your-domain.com/hiapi/callback -d '{}'per verificare che sia raggiungibile e restituisca 2xx. Per il debug su localhost, usa un tunnel pubblico per mappare la porta locale. - Registra prima il callback in modo affidabile, poi restituisci rapidamente 2xx. Alla ricezione della richiesta, scrivi subito il contenuto del callback nel database o in una coda persistente (questa operazione deve essere rapida); dopo il successo della scrittura restituisci 2xx; le operazioni pesanti come download e trasferimento vanno eseguite in background in modo asincrono. Non restituire 200 prima della scrittura: se il processo va in crash subito dopo, il callback va perso e HiAPI, ricevuto il 2xx, non lo riconsegnerà. Inoltre esenta questo percorso dal middleware di autenticazione, poiché i callback di HiAPI non includono i tuoi header di autenticazione.
- Verifica la posizione e i valori di
callback. Assicurati che sia al primo livello del corpo della richiesta (allo stesso livello dimodeleinput), cheurlsia un http(s) pubblico e chewhensiafinal. - Effettua una deduplicazione idempotente in base a
taskId. Alla ricezione del callback verifica prima se questotaskIdè già stato elaborato localmente; se non lo è, scrivilo nel database / attiva le azioni successive; con semantica at-least-once l'arrivo duplicato è normale, non scartarlo come anomalia. - Aggiungi un polling di fallback. Per i
taskIdche superano il tempo previsto senza ricevere il callback, interroga attivamenteGET /v1/tasks/{taskId}per verificare lo stato finale. Il callback è un'ottimizzazione, il polling è la rete di sicurezza: entrambi devono confluire nella stessa logica idempotente. - Trasferisci tempestivamente i prodotti. I
output[].urlnel corpo del callback sono link temporanei (storageètemp,expireAtè un timestamp Unix, scadenza circa 7 giorni); scaricali o trasferiscili immediatamente nel tuo storage, non salvare direttamente hotlink.
Esempio minimo di verifica
Prima di occuparti del callback, dimostra che la tua key e l'integrazione funzionano usando "invio + polling" (con l'id del modello nudo):
# 1. Invia il task
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. Interroga lo stato finale con il taskId restituito
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-xxxx \
-H "Authorization: Bearer $HIAPI_API_KEY"
# → data.status passa da queued/handling/archiving a success (con output) o fail (con error)
Se all'invio ricevi HTTP 401 + {"error":{"code":"permission_denied","type":"hiapi_error","request_id":"..."}}, la API key non è corretta: verificala nella console e riprova. Dopo aver confermato che l'integrazione è corretta, aggiungi il callback di primo livello al corpo della POST e verifica punto per punto il ricevente seguendo i passaggi di correzione sopra.
FAQ
Non ricevo mai il callback, ma il task è effettivamente riuscito: posso comunque ottenere il risultato?
Sì. In qualsiasi momento puoi leggere data.status e data.output con GET /v1/tasks/{taskId}; la perdita del callback non ti impedisce di ottenere attivamente il risultato.
Quante volte viene ritentato il callback e a quali intervalli?
In caso di non 2xx / timeout / errore di rete, la riconsegna segue la sequenza immediata → +1 minuto → +5 minuti → +20 minuti, per un massimo di 4 tentativi. Dopo 4 fallimenti non viene più ritentato e ciò non influisce sullo stato success/fail del task stesso.
È normale ricevere due callback per lo stesso task?
Sì. Il callback di stato finale ha semantica "almeno una volta"; è sufficiente deduplicare in modo idempotente in base a taskId, senza considerare la consegna duplicata un errore.
Come ricevere i callback in fase di sviluppo locale?
HiAPI non può raggiungere localhost né indirizzi di rete interna. Usa un tunnel pubblico per mappare la porta locale sulla rete pubblica, oppure passa direttamente al polling in fase locale e attiva il callback solo dopo la messa in produzione.
Quali campi contiene il corpo della richiesta di callback?
È identico al data di GET /v1/tasks/{taskId} e include taskId, status, output (array dei prodotti in caso di successo), error (con code e message in caso di fallimento), created, completed, ecc. Per i dettagli consulta la documentazione sul dettaglio del task.
Se non ricevo il callback vengo addebitato di più? No. Il fallimento del task stesso non comporta addebiti e la quota riservata viene restituita; il successo o meno della consegna del callback non modifica il risultato della fatturazione del task, che dipende solo dalla generazione finale riuscita o meno.
Articoli correlati
Vedi tutti gli articoli →-
Tutoriale
Come chiamare hailuo-2.3-fast/image-to-video tramite l'API HiAPI: pratica con curl e Python
La prima richiesta funzionante per il livello image-to-video veloce ed economico — dall'ID del modello al download di un MP4
-
Tutoriale
Come chiamare hailuo-2.3/text-to-video tramite l'API HiAPI: curl, Python ed esempi di richiesta eseguibili
-
Tutoriale
Utilizzare Kandinsky 6.0 Pro su HiAPI per la generazione di video da testo: tutorial con curl e Python
Dimostrazione pratica guidata dalla richiesta: costruire la chiamata da prompt a clip video, inviare la richiesta, monitorare lo stato di completamento e scaricare il risultato