Blog/developers·8. Okt. 2026·7 Min.·vom eroq-Team
GPT Image, Nano Banana, Seedream API: ein Endpoint, async Jobs
Ruf GPT Image 2.5, Nano Banana Pro, Seedream 5.0 Pro und Flux 3 über einen eroq-Endpoint auf: Request, 202-Jobs, Polling, Batches und Fehler, in curl und JS.
Fünf Bildgeneratoren bedeuten meistens fünf SDKs, fünf Schlüssel, fünf Abrechnungs-Dashboards und fünf verschiedene Vorstellungen davon, was „async“ heißt. Bei eroq ist es ein einziger Endpoint, bei dem sich nur model ändert. OpenAIs GPT Image 2.5, Googles Nano Banana, ByteDances Seedream, Flux 3 von Black Forest Labs und Grok Imagine 2.0 von xAI laufen alle über POST /v1/images/generations, mit demselben Body, demselben asynchronen Vertrag und einem festen Credit-Preis pro Take. Es sind dieselbe Engine, derselbe Preis und dieselben Regeln wie im Studio. Die Referenz steht unter /docs/images; dies ist die praktische Version.
Die Modell-IDs
| Modell | model-ID |
Hersteller | Credits pro Take | Typischer Render |
|---|---|---|---|---|
| GPT Image 2.5 Sunburst | gpt-image-2-5-sunburst |
OpenAI | 31 | etwa 15 s |
| GPT Image 2.5 Flare | gpt-image-2-5-flare |
OpenAI | 31 | etwa 15 s |
| Nano Banana Pro | nano-banana-pro |
124 | etwa 25 s | |
| Nano Banana 2.1 | nano-banana-2-1 |
31 | etwa 8 s | |
| Seedream 5.0 Pro | seedream-5-0-pro |
ByteDance | 36 | etwa 20 s |
| Flux 3 Image | flux-3-image |
Black Forest Labs | 32 | etwa 20 s |
| Grok Imagine 2.0 | grok-imagine-2-0 |
xAI | 32 | etwa 15 s |
Jedes kostet in allen fünf Formaten dasselbe. Flux 3 Image und Grok Imagine 2.0 öffnen sich mit dem Plan Hobby, die übrigen fünf mit Creator; darunter antwortet der Aufruf mit 403 plan_required und berechnet nichts.
Einen Render senden
curl https://eroq.ai/v1/images/generations \
-H "Authorization: Bearer $EROQ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "nano-banana-pro",
"prompt": "An aerial view of a harbour city at blue hour, lit windows and light trails along the quays, layered haze between the towers, crisp architectural detail, cinematic wide shot",
"aspect": "16:9",
"batch": 2
}'
Der Aufruf berechnet den Batch und antwortet sofort mit 202, mit einem Job pro Take:
{
"object": "image.generation",
"jobs": [
{ "id": "b7e6c2d4-…", "poll": "/v1/images/generations/b7e6c2d4-…" },
{ "id": "4f19a0e3-…", "poll": "/v1/images/generations/4f19a0e3-…" }
],
"created": 1791450000,
"model": "nano-banana-pro",
"failed": 0,
"usage": { "credits_spent": 248, "credits_remaining": 752 }
}
Die Felder, auf die es bei diesen Engines ankommt:
model: immer mitsenden. Fehlt es, gilt standardmäßigeroq-uncensored; eine unbekannte ID antwortet mit400 invalid_bodyund der Liste der gültigen.prompt: der gesamte Auftrag. Setze Schrift in doppelte Anführungszeichen.aspect:1:1(der Standard),3:4,4:3,9:16oder16:9, nativ gerendert.batch: 1 bis 4 Takes, im Voraus berechnet.failedzählt Takes, die nicht starten konnten und bereits erstattet sind.store:truefür eine dauerhafte öffentliche URL, zusätzlich 2 Credits pro angefangene 10 MB.folder_id: legt den Render direkt in einem deiner Bibliotheksordner ab.
Was diese Engines ignorieren
Die Engines oben sind reine Text-zu-Bild-Engines, und einige Felder bewirken bei ihnen nichts:
referenceswerden verworfen. Für ein Gesicht oder Produkt, das zu Fotos passen muss, schick die Anfrage aneroq-one(bis zu zehn Bilder) odereroq-krea2(bis zu vier).negative_promptundcfg_scalebestehen die Validierung, werden von diesen Engines aber nicht verwendet. Beschreibe das gewünschte Ergebnis im Prompt.edit: trueantwortet mit400 edit_unsupported, undaspect: "retain"mit400 retain_requires_reference. Beides sind Bildoperationen; leite sie an Eroq One.
Pollen, bis der Job abgeschlossen ist
const BASE = 'https://eroq.ai/v1'
const headers = {
Authorization: `Bearer ${process.env.EROQ_API_KEY}`,
'Content-Type': 'application/json',
}
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
export async function generate(body) {
const res = await fetch(`${BASE}/images/generations`, { method: 'POST', headers, body: JSON.stringify(body) })
const json = await res.json()
if (!res.ok) throw Object.assign(new Error(json.error.message), { status: res.status, code: json.error.code })
// One job per take: each succeeds, or fails and refunds, on its own
return Promise.all(json.jobs.map(job => waitFor(job.id)))
}
async function waitFor(id, { every = 2500, timeout = 11 * 60_000 } = {}) {
const started = Date.now()
while (Date.now() - started < timeout) {
const res = await fetch(`${BASE}/images/generations/${id}`, { headers })
const job = await res.json()
if (!res.ok) return { id, error: job.error?.code ?? `http_${res.status}` }
if (job.status === 'succeeded') {
const [image] = job.data
return { id, url: image.url, libraryId: image.library_id, ms: job.generation_ms }
}
if (job.status === 'failed') return { id, error: job.error.code } // credits already back
await sleep(every) // processing: phase is "queued" or "generating"
}
return { id, error: 'client_timeout' }
}
Polling ist kostenlos, und alle paar Sekunden ist der vorgesehene Takt. Mach weiter, bis status succeeded oder failed ist. Die Webhooks image.generation.succeeded und image.generation.failed sind eine zusätzliche Benachrichtigung, kein Ersatz; der Leitfaden zur asynchronen API zeigt, wie du ihre Signatur prüfst.
Bei Erfolg ist data[0].url eine signierte URL, die 30 Minuten gilt. Job-IDs leben 24 Stunden, und ein erneutes Abrufen des Jobs (oder des Werks über library_id) erzeugt eine frische URL. Sende store: true, wenn deine Nutzer eine Adresse brauchen, die sich nie ändert. generation_ms ist die tatsächliche Renderzeit, und ein Job, der über die serverseitige Frist von 10 Minuten hinaus noch läuft, wird mit generation_timeout als fehlgeschlagen markiert und erstattet. Deshalb liegt das Client-Timeout oben knapp darüber.
Batches, kurz gefasst
Ein Batch ist ein Aufruf, ein Prompt und bis zu vier Takes. Jeder Take ist ein eigener Job, also pollst du sie parallel und behältst den besten; ein fehlgeschlagener Take wird erstattet, ohne die anderen zu berühren. Ein Batch zählt außerdem als ein einziger Aufruf für das Rate-Limit pro Minute. Für vier verschiedene Prompts schickst du vier Aufrufe.
Fehler
| Status | code |
Was passiert ist | Was zu tun ist |
|---|---|---|---|
| 400 | invalid_body |
Ein Feld hat die Validierung nicht bestanden | Body korrigieren; die Meldung nennt das Feld |
| 400 | content_blocked |
Von der Nutzungsrichtlinie abgelehnt, vor jeder Berechnung | Prompt ändern, nicht unverändert wiederholen |
| 400 | edit_unsupported |
Bildoperation an eine reine Text-Engine geschickt | eroq-one verwenden |
| 402 | insufficient_credits |
Guthaben unter Preis × Batch | Aufladen; nie in einer Schleife wiederholen |
| 403 | plan_required |
Das Modell braucht einen höheren Plan, vor jeder Berechnung | Upgrade oder ein Modell wählen, das dein Plan enthält |
| 429 | rate_limit_exceeded |
Zu viele Aufrufe in dieser Minute mit diesem Schlüssel | Auf Retry-After warten |
| 502 | generation_failed |
Der Render konnte nicht starten | Nicht berechnet; wiederholen |
| 503 | model_unavailable |
Die Engine ist in diesem Deployment offline | Nicht berechnet; eine andere ID wählen |
| 404 | not_found |
Unbekannte Job-ID oder älter als 24 Stunden | IDs und Bilder rechtzeitig sichern |
Ein Job, der mit failed endet, trägt den error.code content_blocked (der Anbieter hat ihn abgelehnt), generation_failed oder generation_timeout, und seine Credits sind bereits wieder im Wallet. Pläne erhöhen das Limit pro Minute für jeden Schlüssel: 2× bei Creator, 4× bei Studio.
Nach Aufgabe routen
const ENGINE = {
text: 'gpt-image-2-5-sunburst', // posters, packaging, UI mockups
keyArt: 'gpt-image-2-5-flare', // dramatic, cinematic frames
detail: 'seedream-5-0-pro', // texture, architecture, landscapes
hero: 'nano-banana-pro', // the final frame, top fidelity
draft: 'nano-banana-2-1', // fast iteration
explore: 'grok-imagine-2-0', // many directions, characterful
daylight: 'flux-3-image', // natural light and typography
}
model: "auto" lässt den Router von eroq unter den Engines wählen, die dein Plan freischaltet, und berechnet die gewählte, die in model zurückgemeldet wird. Das kann Nano Banana Pro für 124 Credits / Bild sein, nenne das Modell also immer, wenn Kosten eine Rolle spielen. Die Rechnung pro Take steht in was KI-Bilder 2026 kosten, und die besten KI-Bildmodelle 2026 erklärt die Routing-Entscheidungen.
MCP und CLI
Dieselben Modelle stehen hinter dem Tool generate_image des MCP-Servers, das auf den Render wartet und das Bild zurückgibt (mit get_image_status für langsame), und hinter der CLI: eroq image "a foggy harbour at dawn" -m seedream-5-0-pro --aspect 16:9 -o harbour.webp. Die Einrichtung für beides steht unter /docs/mcp.
Häufige Fragen
Brauche ich API-Schlüssel von OpenAI, Google oder ByteDance?
Nein. Ein eroq-Schlüssel deckt jedes Modell ab, und alles wird in eroq-Credits aus einem Wallet abgerechnet.
Kann ich über eroq ein Referenzbild an Nano Banana Pro oder GPT Image 2.5 schicken?
Nein. Bei eroq sind sie Text-zu-Bild-Engines, und Referenzen werden verworfen. Für bildgesteuerte Arbeit nimm eroq-one, das bis zu zehn Referenzen liest und per Anweisung bearbeitet.
Wie lange gilt die Bild-URL?
Die signierte URL in data gilt 30 Minuten und der Job 24 Stunden. Ruf ihn erneut ab, um eine frische URL zu bekommen, oder sende mit store: true für eine dauerhafte öffentliche.
Kosten fehlgeschlagene oder blockierte Renders Credits?
Nein. Ein per Richtlinie abgelehnter Prompt wird vor jeder Berechnung beantwortet, und ein Job, der fehlschlägt oder beim Anbieter abgelehnt wird, wird automatisch erstattet.
Hol dir einen Schlüssel, wähl eine Modell-ID und schick eine Anfrage an /docs/images.
In eroq machen
Baue es auf der API
Ein API-Schlüssel ist in einer Minute da. Dieselben Engines, dieselben Preise, asynchrone Jobs und Webhooks.
40 Gratis-Credits · keine Kreditkarte · Privatmodus für jedes Konto
