Rabatt auf Premium-Pläne, wenn du dich registrierstRabatt sichern
eroq

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 Google 124 etwa 25 s
Nano Banana 2.1 nano-banana-2-1 Google 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äßig eroq-uncensored; eine unbekannte ID antwortet mit 400 invalid_body und 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:16 oder 16:9, nativ gerendert.
  • batch: 1 bis 4 Takes, im Voraus berechnet. failed zählt Takes, die nicht starten konnten und bereits erstattet sind.
  • store: true fü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:

  • references werden verworfen. Für ein Gesicht oder Produkt, das zu Fotos passen muss, schick die Anfrage an eroq-one (bis zu zehn Bilder) oder eroq-krea2 (bis zu vier).
  • negative_prompt und cfg_scale bestehen die Validierung, werden von diesen Engines aber nicht verwendet. Beschreibe das gewünschte Ergebnis im Prompt.
  • edit: true antwortet mit 400 edit_unsupported, und aspect: "retain" mit 400 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.

Tagsimage-apigpt-imagenano-bananaseedreamflux-3async

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