Qwen-ImageRiferimento API
Genera e modifica immagini con i modelli Qwen-Image dal codice: una guida rapida in tre passaggi, ogni campo, crediti per immagine, webhook e idempotenza.
L'accesso all'API per sviluppatori è su richiesta.
L'API per le immagini è in beta e i suoi campi possono cambiare. Lo studio non è interessato.
Guida rapidain tre chiamate
Imposta una chiave, invia il lavoro con un tetto di prezzo, poi leggi il risultato.
- 01
Imposta la chiave
L'accesso all'API per sviluppatori è su richiesta: chiedilo nello studio, in Chiavi API. La chiave viene mostrata una sola volta, quindi salvala in una variabile d'ambiente.
export API_KEY="sk_test_…" - 02
Invia il lavoro
Invia l'immagine con POST, un Idempotency-Key e un tetto max_credits. I modelli di modifica accettano anche image_url. Ricevi un 202 e un lavoro in coda, e i crediti vengono riservati.
curl https://api.pershot.app/v1/images/generations \ -H "Authorization: Bearer $API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "model": "qwen-image-2512", "prompt": "A ceramic mug on a walnut table, soft window light, product photo", "size": "1K", "aspect_ratio": "1:1", "max_credits": 2 }'{ "id": "job_01J9ZK4T8W", "object": "job", "kind": "image", "status": "queued", "money_status": "reserved", "queue_position": 2, "requested_model": "qwen-image-2512", "credits_quoted": 2, "credits_charged": null } - 03
Leggi il risultato
Fai GET del lavoro finché lo stato non è succeeded. outputs[].url è firmato e scade dopo 24 ore, quindi scarica ciò che vuoi tenere.
curl https://api.pershot.app/v1/jobs/job_01J9ZK4T8W \ -H "Authorization: Bearer $API_KEY"
Parametrie limiti
Letti dal documento OpenAPI, generato dagli stessi schemi con cui l'API convalida le richieste. I campi sconosciuti vengono rifiutati.
| Campo | Tipo | Valori ammessi | Note |
|---|---|---|---|
modelObbligatorio | string | qwen-image-2512-lightning · qwen-image-2512 · qwen-image-edit-2511-lightning · qwen-image-edit-2511 | L'id del modello. |
promptObbligatorio | string | 2–2000 caratteri | Cosa generare: il soggetto, la camera e la luce. |
sizePredefinito: "1K" | string | 1K · 2K | 1K per bozze e primi fotogrammi, 2K per il dettaglio. |
aspect_ratioPredefinito: "1:1" | string | 16:9 · 9:16 · 1:1 | Forma del fotogramma. |
image_urlFacoltativo | string | URL https | Primo fotogramma per il video; l'immagine di partenza per i modelli di modifica. Un URL https pubblico o un URL di caricamento. |
seedFacoltativo | integer | 0–2.147.483.647 | Ripete un risultato con gli stessi input. |
quote_idFacoltativo | string | qt_… | Esegue al prezzo di un preventivo di POST /v1/quotes, valido per 10 minuti. |
max_creditsFacoltativo | number | > 0 | Il massimo che questo lavoro può costare. Oltre questa cifra il lavoro viene rifiutato, mai addebitato. |
webhook_urlFacoltativo | string | URL https | Un URL https che riceve gli eventi del lavoro. |
end_user_idFacoltativo | string | 1–128 caratteri | Per gli account sviluppatore approvati (accesso su richiesta): il tuo ID utente per questa richiesta, mostrato nell'utilizzo. |
project_idFacoltativo | string | prj_… | |
shot_idFacoltativo | string | sht_… | |
routing_preferenceFacoltativo | string | stability · speed |
Invia esattamente uno tra quote_id e max_credits. Questo endpoint rifiuta model "auto": per i video, chiama prima POST /v1/auto/plan, poi invia il modello scelto con max_credits.
- Modelli
qwen-image-2512-lightningGenerazione · Qwen-Image-2512 · Lightning 4-stepqwen-image-edit-2511-lightningModifica · Qwen-Image-Edit-2511 · Lightningqwen-image-2512Generazione · Qwen-Image-2512qwen-image-edit-2511Modifica · Qwen-Image-Edit-2511- Frequenza e lavori simultanei
- Per impostazione predefinita, 60 richieste al minuto per chiave e 3 lavori alla volta per account. Più chiavi non aumentano i lavori simultanei.
- Per gli agenti IA
- Testo semplice per gli agenti IA: input, valori ammessi, ogni prezzo e un esempio di richiesta
qwen-image-2512-lightningqwen-image-2512qwen-image-edit-2511-lightningqwen-image-edit-2511
Limiti
Letti dalla stessa tabella su cui si basano i controlli dell'API. Ogni riga indica chi controlla il limite e cosa succede se lo superi.
- ApplicatoLo controlliamo noi e rispondiamo 400 prima di qualsiasi preventivo o riserva.
- FornitoreLo controlla il fornitore. Un lavoro che rifiuta non riesce, e non viene addebitato nulla.
- ConsigliatoNessuno lo controlla. Restarci dentro dà risultati migliori.
| Limite | Valore | Unità | Chi controlla | Oltre il limite |
|---|---|---|---|---|
| Richiesta | ||||
Lunghezza del promptprompt | da 2 a 2000 | caratteri | Applicato | 400 invalid_request su prompt, prima di qualsiasi preventivo o riserva. |
Dimensione dell'immaginesize | 1K, 2KPredefinito 1K | – | Applicato | 400 invalid_request su size. |
Proporzioniaspect_ratio | 16:9, 9:16, 1:1Predefinito 1:1 | – | Applicato | 400 invalid_request su aspect_ratio. |
| Immagini che invii | ||||
Immagine di partenzaimage_url | Nessuno | – | Applicato | I modelli di modifica richiedono image_url e quelli di generazione lo rifiutano: 400 invalid_request su image_url. |
| Risultato | ||||
| Pixel in uscita | 1K16:91344×7689:16768×13441:11024×10242K16:92048×11529:161152×20481:12048×2048 | px | Applicato | Chiediamo esattamente queste dimensioni. |
| Lato in uscita | da 256 a 2048 | px per lato | Fornitore | Tutte le dimensioni qui sopra rientrano. Il fornitore rifiuta quelle più grandi. |
| Formato di uscita | JPEG | – | Applicato | Ogni immagine è un JPEG. |
| Link | ||||
| Link del risultato | 24 | ore | Applicato | Dopo, il link risponde 403. Richiedi di nuovo il lavoro con GET per avere un link nuovo. Il file resta conservato per 12 mesi (outputs_expire_at del lavoro indica la data), più a lungo se il risultato è salvato in Risorse o usato in un progetto. |
| Limite | Valore | Unità | Chi controlla | Oltre il limite |
|---|---|---|---|---|
| Richiesta | ||||
Lunghezza del promptprompt | da 2 a 2000 | caratteri | Applicato | 400 invalid_request su prompt, prima di qualsiasi preventivo o riserva. |
Dimensione dell'immaginesize | 1K, 2KPredefinito 1K | – | Applicato | 400 invalid_request su size. |
Proporzioniaspect_ratio | 16:9, 9:16, 1:1Predefinito 1:1 | – | Applicato | 400 invalid_request su aspect_ratio. |
| Immagini che invii | ||||
Immagine di partenzaimage_url | Esattamente 1 | – | Applicato | I modelli di modifica richiedono image_url e quelli di generazione lo rifiutano: 400 invalid_request su image_url. |
Dimensione del caricamentofile | fino a 10 | MB | Applicato | POST /v1/uploads risponde 400 invalid_request su file. |
Formati di caricamentofile | JPEG, PNG, WebP | – | Applicato | Letto dal file stesso, non dal suo nome. Qualsiasi altro formato: 400 invalid_request su file. |
| Risultato | ||||
| Pixel in uscita | 1K16:91344×7689:16768×13441:11024×10242K16:92048×11529:161152×20481:12048×2048 | px | Applicato | Chiediamo esattamente queste dimensioni. |
| Lato in uscita | da 512 a 2048 | px per lato | Fornitore | Tutte le dimensioni qui sopra rientrano. Il fornitore rifiuta quelle più grandi. |
| Formato di uscita | JPEG | – | Applicato | Ogni immagine è un JPEG. |
| Link | ||||
| Link di caricamento | 7 | giorni | Applicato | Dopo, il link risponde 403. Carica di nuovo il file. |
| Link del risultato | 24 | ore | Applicato | Dopo, il link risponde 403. Richiedi di nuovo il lavoro con GET per avere un link nuovo. Il file resta conservato per 12 mesi (outputs_expire_at del lavoro indica la data), più a lungo se il risultato è salvato in Risorse o usato in un progetto. |
Non scarichiamo mai immagini da altri host, quindi per quei link la dimensione la controlla il fornitore, e un lavoro che rifiuta non viene addebitato. Gli stessi limiti sono disponibili in JSON: GET /v1/models restituisce un oggetto limits per ogni modello.
Prezzicalcolati in modo trasparente
Un prezzo per immagine, in base a modello e dimensioni, in crediti (1 US$ = 100 crediti). Generazione e modifica hanno prezzi separati.
| Modello | 1K | 2K |
|---|---|---|
qwen-image-2512-lightningGenerazione | 1 cr≈ 0,01 $≈ 1000 immagini ogni 10 $ | 3 cr≈ 0,03 $≈ 333 immagini ogni 10 $ |
qwen-image-edit-2511-lightningModifica | 2 cr≈ 0,02 $≈ 500 immagini ogni 10 $ | 4 cr≈ 0,04 $≈ 250 immagini ogni 10 $ |
qwen-image-2512Generazione | 2 cr≈ 0,02 $≈ 500 immagini ogni 10 $ | 6 cr≈ 0,06 $≈ 166 immagini ogni 10 $ |
qwen-image-edit-2511Modifica | 3 cr≈ 0,03 $≈ 333 immagini ogni 10 $ | 10 cr≈ 0,10 $≈ 100 immagini ogni 10 $ |
Webhooke idempotenza
I nuovi tentativi non addebitano mai due volte e non devi interrogare lo stato di continuo.
- Idempotenza
- Ogni POST di generazione richiede un Idempotency-Key (da 1 a 255 caratteri ASCII visibili). La stessa chiave entro 24 ore restituisce lo stesso lavoro con HTTP 200, quindi un nuovo tentativo dopo un timeout non crea né addebita mai un secondo lavoro.
- Prompt rifiutati
- Un prompt rifiutato dal controllo preliminare (422 content_rejected) non crea nulla, quindi puoi riusare la stessa chiave con un nuovo prompt.
- Eventi
job.queuedjob.processingjob.succeededjob.failedjob.cancelled- Firma
- X-Signature contiene t, l'ora unix, e v1, un HMAC-SHA256 di t, un punto e il corpo grezzo, con il tuo segreto whsec_ come chiave. Rifiuta i timestamp più vecchi di cinque minuti ed elimina i duplicati con X-Event-Id.
- Consegna
- Una risposta 2xx entro 10 secondi vale come consegnata. Le consegne non riuscite vengono ritentate dopo 1 min, 5 min, 30 min, 2 h e 6 h. I reindirizzamenti non vengono seguiti.
{
"id": "evt_01J9ZKB1QX",
"type": "job.succeeded",
"created_at": "2026-09-29T14:02:31Z",
"data": {
"job": {
"id": "job_01J9ZK4T8W",
"object": "job",
"kind": "image",
"status": "succeeded",
"money_status": "settled",
"requested_model": "qwen-image-2512",
"credits_charged": 2,
"outputs": [
{
"kind": "image",
"url": "https://…/job_01J9ZK4T8W.png?sig=…"
}
]
}
}
}import { createHmac, timingSafeEqual } from "node:crypto";
// rawBody: the request body exactly as received, before any JSON parsing.
export function verifyWebhook(header, rawBody, secret, toleranceSec = 300) {
let t = null;
const signatures = [];
for (const item of (header ?? "").split(",")) {
const [key, value] = item.split("=", 2);
if (key === "t") t = Number(value);
if (key === "v1") signatures.push(Buffer.from(value, "hex"));
}
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest();
return signatures.some((s) => s.length === expected.length && timingSafeEqual(s, expected));
}
// verifyWebhook(req.headers["x-signature"], rawBody, process.env.WEBHOOK_SECRET)
// Answer 2xx quickly, and skip an X-Event-Id you have already handled.Errorie cosa fare
Ogni errore ha la stessa forma: un oggetto error con code, message, param e request_id. Quelli che incontrerai più spesso:
| Codice | HTTP | Cosa fare |
|---|---|---|
invalid_request | 400 | Correggi il campo indicato in param. |
unauthorized | 401 | Controlla la chiave e l'header Bearer. |
insufficient_credits | 402 | Fai una ricarica, poi riprova con lo stesso Idempotency-Key. |
forbidden_model | 403 | Aggiungi il modello o lo strumento all'elenco consentito della chiave nello studio, oppure usa un'altra chiave. Strumenti come Migliora hanno bisogno di una voce propria. |
quote_expired | 409 | Chiedi un nuovo preventivo; i preventivi durano 10 minuti. |
price_changed | 409 | Il prezzo ha superato il tuo tetto. Chiedi un nuovo preventivo o alza max_credits. |
content_rejected | 422 | Non è stato addebitato nulla. Cambia il prompt o le immagini. |
rate_limited | 429 | Aspetta il tempo indicato da Retry-After, poi riprova. |
upstream_unavailable | 503 | Il modello non è disponibile. Riprova più tardi; un lavoro che non parte mai non viene addebitato. |