status: "failed". I job falliti e annullati non vengono fatturati. Paghi solo per i job completati. In una node app, il job dell’app stessa non viene mai fatturato. Ogni nodo di generazione o LLM viene addebitato quando il suo job si completa. Un fallimento non annulla i nodi paralleli né gli altri rami, quindi anche un nodo che si completa dopo che l’app è già fallita viene addebitato, e questi addebiti non vengono rimborsati. Un nodo che fallisce, viene annullato o non parte mai non viene addebitato. Vedi Chiavi API e fatturazione.
Errori al momento della richiesta e job falliti
Gli errori al momento della richiesta restituiscono uno stato4xx o 5xx. Nessun job viene creato. Leggi il body come descritto di seguito.
I job falliti restituiscono uno stato di successo al momento dell’invio. Effettua polling su GET /jobs/{id} o attendi un webhook. Quando il job termina, status è "failed" e il fallimento si trova nell’oggetto error di primo livello. Non leggere result su un job fallito: viene omesso (oppure è null). Contiene l’output solo quando status è "completed". Un job cancelled non ha né result né error.
Basa la logica su error.code. message può essere omesso e, per provider_error e internal, è testo libero del provider. Non fare il parsing di message.
Body delle risposte
Su generate, jobs, assets, styles e node apps, leggimessage ?? error quando il body è JSON. Uno di questi due campi contiene il riepilogo. Alcuni body 5xx non sono JSON, incluso un 502 il cui body è il testo semplice error code: 502. Effettua il parsing in modo difensivo: se il body non è JSON, basa la logica sullo stato HTTP.
La maggior parte dei fallimenti usa { "message": "..." }, a volte con campi aggiuntivi (limit, jobType, modelAccessDenial). Il JSON non valido e alcuni handler descritti di seguito usano invece { "error": "..." }.
Gli endpoint MCP come /mcp restituiscono errori JSON-RPC, { "jsonrpc", "id", "error": { "code", "message" } }, non i body HTTP descritti in questa pagina.
Invia Accept: application/json
Gli errori { "message" }, inclusi 401 e 404, sono JSON quando Accept è application/json o */*. Quando Accept manca, oppure è text/html, questi stati sono una pagina HTML (Content-Type: text/html) e un parser JSON fallirà.
Questo è importante per i client che non inviano alcun header Accept. Il modulo urllib di Python è uno di questi. curl invia Accept: */* per impostazione predefinita, e lo stesso fa fetch di Node, quindi entrambi ricevono JSON a meno che tu non sovrascriva Accept.
Le chiamate non autenticate a POST /generate/..., GET /jobs/{id}, GET /styles e GET /assets restituiscono 401 {"message":"Unauthorized"} per */* e application/json, e una pagina HTML quando Accept manca o è text/html. Una chiamata autenticata a GET /jobs/{id} con un id sconosciuto si comporta allo stesso modo con lo stato: 404 JSON {"message":"Job not found or unauthorized"} quando Accept richiede JSON, e 404 text/html quando Accept manca.
Il JSON non valido (400) e la validazione (422) usano { "error" } e restano JSON anche quando Accept manca. Lo stesso vale per il 422 dei campi rimossi, il 410 dei modelli dismessi, il 402 di Zero Data Retention, le risposte { "error" } delle node app e gli errori mappati della Agent operation API. Anche i 402 e 429 generati all’ammissione di un job POST /generate/... sono JSON, anche con un Accept da browser.
413 e 500 usano { "message" } e seguono Accept, come 401 e 404.
Validazione (422)
details elenca ogni problema. field è il percorso unito con . ("image_style_references.0.url"). Gli errori a livello di oggetto usano una stringa vuota, come per la chiave sconosciuta qui sopra. Più chiavi sconosciute producono Unrecognized keys: ... e lo stesso field vuoto. expected viene aggiunto solo quando code è "invalid_type".
Un header X-Webhook-URL non valido usa lo stesso 422.
Anche GET /jobs con parametri di query non validi restituisce questo 422. Non è un 400.
Un controllo dell’input di Zero Data Retention che fallisce all’interno dello strumento restituisce 422 con la spiegazione in message (il formato { "message" }, quindi Accept è rilevante). Vedi Zero Data Retention.
Campi rimossi e deprecati (422)
Il campo rimosso batchSize / batch_size usa un 422 diverso. Non c’è alcun array details:
batch_size è rimosso allo stesso modo. field è il nome che hai inviato.
Un alias di campo deprecato usa reason "deprecated_field" o "conflicting_fields", più replacement, sunset_date e migration_url quando applicabili. Basa la logica su error e reason. La frase da mostrare a una persona è message.
Modelli dismessi (410)
Un modello che ha superato la data di dismissione restituisce 410 con Deprecation: true e un header Sunset (una data RFC 1123):
error è il valore stabile "model_unavailable". replacement e migration_url vengono omessi quando non esiste un sostituto consigliato. Ripetere la chiamata allo stesso modello continuerà a restituire 410. Passa a replacement quando è impostato e consulta Deprecazioni.
Un modello deprecato ma ancora attivo invia Deprecation e Sunset in ogni risposta, inclusi gli errori. L’uso di un alias di campo deprecato fa lo stesso, anche nel relativo 422. Quando esiste una guida alla migrazione, viene inviato anche un header Link: <migration_url>; rel="deprecation".
Codici di stato
400
Il JSON non valido su generate è sempre JSON, senza bisogno dell’header Accept:
{ "error" } per un URL di input che non può usare: Invalid URL for input "<key>" oppure Failed to download URL for <key>: …. Il messaggio di download copre anche i fallimenti temporanei, quindi, a differenza di generate (vedi Download degli input), un fallimento del download in una node app è sempre 400. Riprova una volta se l’URL è valido.
Il JSON non valido su POST /node-apps/{id}/execute non è il 400 di generate descritto sopra. Diventa un 500 { "message": "Internal Error" }, senza testo dell’eccezione, e segue Accept.
Le altre risposte 400 su asset e node app sono { "message": "..." } con una breve spiegazione, ad esempio No file provided su un upload presigned o Invalid pagination parameters sulle versioni delle node app. Un upload di asset fallito inoltra lo stato del servizio di upload (400, 401, 404 o 500) e può inserire il testo della sua risposta in message. Questo testo a volte è una stringa JSON. I parametri di query non validi su GET /jobs restituiscono 422, non 400.
401
Generate, jobs, assets, styles e node apps:
{ "message": "Presigned upload URL expired" } oppure { "message": "Invalid presigned upload URL" }.
402 Pagamento richiesto
Per un client fatturato tramite API (una chiave API, o MCP con una chiave API) il cui saldo API non copre il job:
message per 402 sulla API pubblica:
Una chiamata generate con Zero Data Retention su un workspace che non l’ha abilitata restituisce questo body, sempre JSON:
402. Questi attingono dal saldo di unità di calcolo del workspace, non dal saldo API.
403
404
Ogni 404 è { "message" }, ad esempio per un id di job sconosciuto:
Accept mancante rende queste risposte HTML, tranne Endpoint not found per un modello che la tua chiave o il tuo piano non possono usare, che è sempre JSON. Una chiamata autenticata a GET /jobs/{id} con un id sconosciuto e senza Accept restituisce 404 text/html.
Anche un’operazione Agent sconosciuta restituisce
404 { "message": "Endpoint not found" }, non il formato Agent { "error", "code" }.
405
Il body è testo semplice senza header Content-Type, non JSON, anche quando Accept è application/json. Il testo è il metodo seguito da method not allowed, ad esempio GET method not allowed. Un header Allow elenca i metodi accettati dal percorso.
413 Payload troppo grande
Un body della richiesta troppo grande viene rifiutato con 413. Dalla API stessa, il body segue Accept:
413. Non inviare file inline. Carica il file con POST /assets e passa l’URL restituito nella richiesta generate.
Download degli input
Un host che restituisce404 o 410 produce un 422 permanente. Il body è JSON e Accept è rilevante:
410 dell’host usa la stessa frase con 410. Gli altri rifiuti permanenti usano Input file rejected: ….
Un fallimento del download riprovabile è 502 o 504. Basa la logica sul codice di stato, non sul body, e riprova.
Un
502 che continua a ripetersi per lo stesso URL probabilmente indica che l’URL è bloccato o non funzionante. Cambia l’URL.
Anche i fallimenti di conversione dell’export 3D sono 502. Questo percorso non è stato testato dal vivo, quindi anche il body potrebbe arrivare come testo semplice di Cloudflare error code: 502. Basa la logica sul codice di stato e riprova. Un 502 che continua a ripetersi per lo stesso URL del modello probabilmente indica che l’URL è bloccato o non funzionante.
429 di concorrenza
Quando il job non può essere messo in backlog, una richiesta oltre il limite di concorrenza può essere rifiutata con 429 e Content-Type: application/json:
limit è il tuo limite di concorrenza per questo tipo di job. Viene conteggiato per utente, non per workspace. È approssimativo: un breve picco può essere accettato oltre il limite, quindi non contare sul fatto che sia proprio la richiesta limit + 1 a fallire. jobType è una categoria interna di job, non il percorso pubblico del modello. Non basare la logica su di esso.
Krea 2 può anche restituire solo { "message": "CONCURRENCY_LIMIT_REACHED" }, senza limit né jobType, quando la sua coda condivisa è piena. Non si tratta del tuo limite. Attendi e riprova.
Il backlog è attivo solo quando il piano lo include (Pro e superiori), il modello lo supporta e la richiesta non è Zero Data Retention. Al momento le richieste Krea 2 non vengono messe in backlog su nessun piano, quindi restituiscono 429 oltre il limite. Quando il backlog è attivo, il job aggiuntivo viene accettato con status: "backlogged" e parte non appena si libera uno slot. Non esiste un limite separato per il backlog. Vedi Limiti di frequenza.
La API non invia Retry-After né X-RateLimit-*. La risposta include però cf-ray. In caso di 429, riprova con backoff esponenziale dopo che i job in corso sono terminati (effettua polling su GET /jobs/{id} o usa un webhook).
Se un completamento successivo esaurisce il saldo, i job ancora in backlog falliscono con error.code "insufficient_balance". Si tratta di un job fallito, non di un 402 HTTP. Questi job non inviano un webhook, quindi effettua polling su GET /jobs/{id} per i job in backlog.
Agent operation API
POST /agent/{operation} e GET /agent/session/{sessionId} restituiscono { "error", "code"?, "allowedModels"? }. Solo error è obbligatorio. allowedModels è in camelCase. Un turno che fallisce dopo essere stato accettato appare come status: "failed" sulla sessione, non come uno di questi errori HTTP. Vedi Agent.
Un codice di errore Agent non riconosciuto è comunque
422 con { "error", "code" }. Il 404 per operazione sconosciuta e un 500 non gestito usano { "message" } e seguono Accept.
error.code dei job falliti
GET /jobs e GET /jobs/{id} impostano error solo quando status è "failed". Non c’è alcun result utilizzabile:
Le consegne webhook per un job fallito usano lo stesso oggetto job, incluso
error. Una consegna di annullamento non ha error. Un payload più grande di 256 KiB non viene inviato e non vengono effettuate ulteriori consegne per quel job, quindi effettua invece polling su GET /jobs/{id}. Verifica la firma prima di fidarti del body. Vedi Webhook.
Debugging
Non esiste un header di request id di Krea. Ogni risposta include però l’headercf-ray di Cloudflare. Non viene inviato alcun header Retry-After o X-RateLimit-*.
Quando scrivi a support@krea.ai, includi:
job_id, quando la chiamata ha creato o riguardato un job- L’orario e l’endpoint
- Per un errore al momento della richiesta, il valore di
cf-ray
Access-Control-Allow-Origin è *. Su generate, jobs, assets, styles e node apps, Access-Control-Expose-Headers non è impostato, quindi fetch nel browser non può leggere cf-ray, Deprecation o Sunset. Copia cf-ray dal log di rete, oppure da un client lato server.
In ogni risposta, controlla Deprecation e Sunset prima che il modello smetta di accettare chiamate. Vedi Deprecazioni.
Prossimi passi
Ciclo di vita del job
Effettua polling sullo stato finché il job non si completa, fallisce o viene annullato
Webhook
Verifica la firma sulla consegna di un job fallito
Limiti di frequenza
Quando i job aggiuntivi vanno in backlog e quando restituiscono 429
Chiavi API e fatturazione
Ricarica il saldo API dopo un 402