Qwen-ImageAPI-Referenz
Generiere und bearbeite Bilder mit den Qwen-Image-Modellen aus Code: ein Schnellstart in drei Schritten, jedes Feld, Credits pro Bild, Webhooks und Idempotenz.
Zugang zur Entwickler-API gibt es auf Antrag.
Die Bild-API ist in der Beta, und ihre Felder können sich ändern. Das Studio ist nicht betroffen.
Schnellstartin drei Aufrufen
Setze einen Schlüssel, sende den Auftrag mit einer Preisobergrenze und lies dann das Ergebnis.
- 01
Schlüssel setzen
Zugang zur Entwickler-API gibt es auf Antrag: Beantrage ihn im Studio unter API-Schlüssel. Der Schlüssel wird einmal angezeigt, also speichere ihn in einer Umgebungsvariable.
export API_KEY="sk_test_…" - 02
Auftrag senden
Sende das Bild per POST mit einem Idempotency-Key und der Obergrenze max_credits. Bearbeitungsmodelle nehmen außerdem image_url. Du bekommst 202 und einen Auftrag in der Warteschlange, und die Credits werden reserviert.
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
Ergebnis lesen
Rufe den Auftrag per GET ab, bis sein Status succeeded ist. outputs[].url ist signiert und läuft nach 24 Stunden ab, also lade herunter, was du behalten willst.
curl https://api.pershot.app/v1/jobs/job_01J9ZK4T8W \ -H "Authorization: Bearer $API_KEY"
Parameterund Limits
Gelesen aus dem OpenAPI-Dokument, das aus denselben Schemas erzeugt wird, gegen die die API validiert. Unbekannte Felder werden abgelehnt.
| Feld | Typ | Erlaubt | Hinweise |
|---|---|---|---|
modelErforderlich | string | qwen-image-2512-lightning · qwen-image-2512 · qwen-image-edit-2511-lightning · qwen-image-edit-2511 | Die Modell-ID. |
promptErforderlich | string | 2–2.000 Zeichen | Was generiert werden soll: das Motiv, die Kamera und das Licht. |
sizeStandard "1K" | string | 1K · 2K | 1K für Entwürfe und Startbilder, 2K für Details. |
aspect_ratioStandard "1:1" | string | 16:9 · 9:16 · 1:1 | Bildformat. |
image_urlOptional | string | https-URL | Startbild für Video; das Ausgangsbild für die Bearbeitungsmodelle. Eine öffentliche https-URL oder eine Upload-URL. |
seedOptional | integer | 0–2.147.483.647 | Wiederholt ein Ergebnis bei gleichen Eingaben. |
quote_idOptional | string | qt_… | Ausführung zu einem Preisangebot von POST /v1/quotes, 10 Minuten gültig. |
max_creditsOptional | number | > 0 | Das Höchste, was dieser Auftrag kosten darf. Darüber wird der Auftrag abgelehnt, nie berechnet. |
webhook_urlOptional | string | https-URL | Eine https-URL, die die Ereignisse des Auftrags empfängt. |
end_user_idOptional | string | 1–128 Zeichen | Für freigegebene Entwicklerkonten (Zugang auf Antrag): deine eigene Nutzer-ID für diese Anfrage, sichtbar in der Nutzung. |
project_idOptional | string | prj_… | |
shot_idOptional | string | sht_… | |
routing_preferenceOptional | string | stability · speed |
Sende genau eins von beiden: quote_id oder max_credits. Dieser Endpunkt lehnt model "auto" ab: Für Videos ruf zuerst POST /v1/auto/plan auf und sende dann das gewählte Modell mit max_credits.
- Modelle
qwen-image-2512-lightningGenerieren · Qwen-Image-2512 · Lightning 4-stepqwen-image-edit-2511-lightningBearbeiten · Qwen-Image-Edit-2511 · Lightningqwen-image-2512Generieren · Qwen-Image-2512qwen-image-edit-2511Bearbeiten · Qwen-Image-Edit-2511- Ratenlimit und Parallelität
- Standardmäßig 60 Anfragen pro Minute pro Schlüssel und 3 gleichzeitige Aufträge pro Konto. Mehr Schlüssel bringen keine zusätzliche Parallelität.
- Für KI-Agenten
- Klartext für KI-Agenten: Eingaben, zulässige Werte, jeder Preis und ein Anfragebeispiel
qwen-image-2512-lightningqwen-image-2512qwen-image-edit-2511-lightningqwen-image-edit-2511
Limits
Aus derselben Tabelle gelesen, gegen die die API prüft. Jede Zeile zeigt, wer das Limit prüft und was passiert, wenn es überschritten wird.
- ErzwungenWir prüfen es und antworten mit 400, bevor ein Preisangebot erstellt oder etwas reserviert wird.
- Beim LieferantenDer Anbieter prüft es. Ein Auftrag, den er ablehnt, schlägt fehl, und es wird nichts berechnet.
- EmpfohlenNiemand prüft es. Wenn du darunter bleibst, bekommst du bessere Ergebnisse.
| Limit | Wert | Einheit | Wer prüft | Bei Überschreitung |
|---|---|---|---|---|
| Anfrage | ||||
Prompt-Längeprompt | 2 bis 2.000 | Zeichen | Erzwungen | 400 invalid_request bei prompt, vor jedem Preisangebot und jeder Reservierung. |
Bildgrößesize | 1K, 2KStandard 1K | – | Erzwungen | 400 invalid_request bei size. |
Seitenverhältnisaspect_ratio | 16:9, 9:16, 1:1Standard 1:1 | – | Erzwungen | 400 invalid_request bei aspect_ratio. |
| Bilder, die du sendest | ||||
Ausgangsbildimage_url | Keine | – | Erzwungen | Bearbeitungsmodelle brauchen image_url, Generierungsmodelle lehnen es ab: 400 invalid_request bei image_url. |
| Ausgabe | ||||
| Ausgabepixel | 1K16:91344×7689:16768×13441:11024×10242K16:92048×11529:161152×20481:12048×2048 | px | Erzwungen | Wir fordern genau diese Größen an. |
| Seitenlänge der Ausgabe | 256 bis 2.048 | px pro Seite | Beim Lieferanten | Alle Größen oben passen. Größere lehnt der Anbieter ab. |
| Ausgabeformat | JPEG | – | Erzwungen | Jedes Bild ist ein JPEG. |
| Links | ||||
| Ausgabe-Link | 24 | Stunden | Erzwungen | Danach antwortet der Link mit 403. Ruf den Auftrag erneut per GET ab, um einen neuen Link zu bekommen. Die Datei selbst wird 12 Monate aufbewahrt (outputs_expire_at des Auftrags nennt das Datum), länger, wenn das Ergebnis in der Mediathek gespeichert oder in einem Projekt verwendet wird. |
| Limit | Wert | Einheit | Wer prüft | Bei Überschreitung |
|---|---|---|---|---|
| Anfrage | ||||
Prompt-Längeprompt | 2 bis 2.000 | Zeichen | Erzwungen | 400 invalid_request bei prompt, vor jedem Preisangebot und jeder Reservierung. |
Bildgrößesize | 1K, 2KStandard 1K | – | Erzwungen | 400 invalid_request bei size. |
Seitenverhältnisaspect_ratio | 16:9, 9:16, 1:1Standard 1:1 | – | Erzwungen | 400 invalid_request bei aspect_ratio. |
| Bilder, die du sendest | ||||
Ausgangsbildimage_url | Genau 1 | – | Erzwungen | Bearbeitungsmodelle brauchen image_url, Generierungsmodelle lehnen es ab: 400 invalid_request bei image_url. |
Upload-Größefile | bis 10 | MB | Erzwungen | POST /v1/uploads antwortet mit 400 invalid_request bei file. |
Upload-Formatefile | JPEG, PNG, WebP | – | Erzwungen | Wird aus der Datei selbst gelesen, nicht aus ihrem Namen. Alles andere: 400 invalid_request bei file. |
| Ausgabe | ||||
| Ausgabepixel | 1K16:91344×7689:16768×13441:11024×10242K16:92048×11529:161152×20481:12048×2048 | px | Erzwungen | Wir fordern genau diese Größen an. |
| Seitenlänge der Ausgabe | 512 bis 2.048 | px pro Seite | Beim Lieferanten | Alle Größen oben passen. Größere lehnt der Anbieter ab. |
| Ausgabeformat | JPEG | – | Erzwungen | Jedes Bild ist ein JPEG. |
| Links | ||||
| Upload-Link | 7 | Tage | Erzwungen | Danach antwortet der Link mit 403. Lade die Datei erneut hoch. |
| Ausgabe-Link | 24 | Stunden | Erzwungen | Danach antwortet der Link mit 403. Ruf den Auftrag erneut per GET ab, um einen neuen Link zu bekommen. Die Datei selbst wird 12 Monate aufbewahrt (outputs_expire_at des Auftrags nennt das Datum), länger, wenn das Ergebnis in der Mediathek gespeichert oder in einem Projekt verwendet wird. |
Wir laden nie Bilder von anderen Hosts, daher prüft bei solchen Links der Anbieter die Größe, und ein Auftrag, den er ablehnt, wird nicht berechnet. Dieselben Limits gibt es auch als JSON: GET /v1/models liefert für jedes Modell ein limits-Objekt.
Preiseoffen nachgerechnet
Ein Preis pro Bild, nach Modell und Größe, in Credits (1 US$ = 100 Credits). Generieren und Bearbeiten haben getrennte Preise.
| Modell | 1K | 2K |
|---|---|---|
qwen-image-2512-lightningGenerieren | 1 cr≈ 0,01 $≈ 1.000 Bilder pro 10 $ | 3 cr≈ 0,03 $≈ 333 Bilder pro 10 $ |
qwen-image-edit-2511-lightningBearbeiten | 2 cr≈ 0,02 $≈ 500 Bilder pro 10 $ | 4 cr≈ 0,04 $≈ 250 Bilder pro 10 $ |
qwen-image-2512Generieren | 2 cr≈ 0,02 $≈ 500 Bilder pro 10 $ | 6 cr≈ 0,06 $≈ 166 Bilder pro 10 $ |
qwen-image-edit-2511Bearbeiten | 3 cr≈ 0,03 $≈ 333 Bilder pro 10 $ | 10 cr≈ 0,10 $≈ 100 Bilder pro 10 $ |
Webhooksund Idempotenz
Wiederholte Anfragen werden nie doppelt berechnet, und du musst nicht ständig abfragen.
- Idempotenz
- Jeder Generierungs-POST braucht einen Idempotency-Key (1 bis 255 sichtbare ASCII-Zeichen). Derselbe Schlüssel innerhalb von 24 Stunden liefert denselben Auftrag mit HTTP 200, also erzeugt oder berechnet eine Wiederholung nach einem Timeout nie einen zweiten Auftrag.
- Abgelehnte Prompts
- Ein Prompt, den die Vorprüfung ablehnt (422 content_rejected), erzeugt nichts, also kannst du denselben Schlüssel mit einem neuen Prompt wieder verwenden.
- Ereignisse
job.queuedjob.processingjob.succeededjob.failedjob.cancelled- Signatur
- X-Signature enthält t, die Unix-Zeit, und v1, einen HMAC-SHA256 über t, einen Punkt und den Rohbody, mit deinem whsec_-Secret als Schlüssel. Lehne Zeitstempel ab, die älter als fünf Minuten sind, und entferne Duplikate anhand von X-Event-Id.
- Zustellung
- Ein 2xx innerhalb von 10 Sekunden gilt als zugestellt. Fehlgeschlagene Zustellungen werden nach 1 min, 5 min, 30 min, 2 h und 6 h wiederholt. Weiterleitungen werden nicht verfolgt.
{
"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.Fehlerund was zu tun ist
Jeder Fehler hat dieselbe Form: ein error-Objekt mit code, message, param und request_id. Die, auf die du am ehesten triffst:
| Code | HTTP | Was tun |
|---|---|---|
invalid_request | 400 | Korrigiere das Feld, das in param genannt wird. |
unauthorized | 401 | Prüfe den Schlüssel und den Bearer-Header. |
insufficient_credits | 402 | Lade auf und versuch es dann mit demselben Idempotency-Key erneut. |
forbidden_model | 403 | Füge das Modell oder Tool im Studio zu den erlaubten Modellen und Tools des Schlüssels hinzu, oder nutze einen anderen Schlüssel. Tools wie „Verbessern“ brauchen einen eigenen Eintrag. |
quote_expired | 409 | Hol ein neues Preisangebot ein; Preisangebote gelten 10 Minuten. |
price_changed | 409 | Der Preis ist über deine Obergrenze gestiegen. Hol ein neues Preisangebot ein oder erhöhe max_credits. |
content_rejected | 422 | Es wurde nichts berechnet. Ändere den Prompt oder die Bilder. |
rate_limited | 429 | Warte die Zeit aus Retry-After ab und versuch es dann erneut. |
upstream_unavailable | 503 | Das Modell ist nicht verfügbar. Versuch es später erneut; ein Auftrag, der nie startet, wird nicht berechnet. |