Use this API when you would otherwise be holding an HTTP connection open for
20–50 seconds. If you already have a synchronous integration that works, see
Choosing sync or async before migrating.
Endpoints
Note the path is plural on create and singular on read. There is no list,
cancel, or delete endpoint.
Create a task
The request body is always the same three-key envelope:model, input, and an optional callback_url.
Envelope fields
Unknown keys at the envelope level are currently accepted and ignored — do not
rely on that, and do not put generation parameters there. They belong in
input.
The input object
input carries the generation parameters, and which fields it accepts depends
on the model. The envelope around it is fixed; the contents are not.
Validation inside input is strict — any key the model does not recognize is
rejected outright, which makes a typo loud instead of silent:
Nano Banana series
The full field list, resolution tiers, aspect ratios and image editing.
Poll for the result
Task fields
The response grows as the task advances —
outputs and expires_at simply are
not there while the task is still running. Read fields defensively rather than
assuming a fixed shape, and branch on status first.
Status flow
How long to wait
Submitting is sub-second and stays that way under load: measured p50 0.88 s, p95 0.92 s across 30 tasks at concurrency 12. The generation itself is where the time goes — roughly 12–50 seconds depending on model and resolution, with 0–11 seconds of that spent queued. Per-model figures live on the model’s own page.Downloading outputs
outputs holds plain https URLs with no signature or query string, served
from WideRouter’s delivery CDN — a different hostname from the API. Two things
follow from that:
1
They are unauthenticated
Do not send your API key to them, and treat the URL itself as the secret.
Anyone holding the link can fetch the image for as long as it lives.
2
They expire after 24 hours
expires_at is always created_at plus 86400. Copy anything you need to
keep into your own storage — do not store output URLs as permanent references.1K, 2.4–3.0 MB at 2K, and 7.5–8.2 MB at 4K.
Read the Content-Type from the response instead of assuming a file extension.
Callbacks
Setcallback_url on create and WideRouter posts the finished task to it, so
you can skip polling entirely.
https. Anything else — http, a bare hostname, a non-string —
is rejected at submit time with invalid_callback_url, so a typo fails fast
instead of silently never delivering.
WideRouter posts the task object as application/json, with headers you can
route on before parsing the body:
The body is byte-identical to what
GET /v1/task/{task_id} returns at that
moment — same fields, same values — so one handler can serve both paths.
Delivery was immediate in testing: callbacks for three tasks all arrived within
a second of the task reaching completed. If your endpoint answers with a 5xx,
WideRouter retries; observed attempts were at roughly 0, 10 and 70 seconds.
A callback is a latency optimization, not a delivery guarantee. Keep a polling
fallback for tasks whose callback never arrives, and make your handler
idempotent — key it on the task
id, since retries mean the same task can
arrive more than once.When a task fails
Afailed task is still a 200 on the read endpoint. The failure is in the
body, not the HTTP status:
outputs and no expires_at. Input-fetch failures are fast —
under a second — because they happen before any model work.
Errors on submit
Validation happens before anything is queued, so a400 here costs nothing.
Errors point at one field at a time, and
param uses full paths including array
indices (input.images[0]), so you can map a failure straight onto your request.
Which models work here
Model ids are matched exactly. There are no aliases, and-preview suffixed
names are not accepted. Sending an id the async API does not serve returns
model_not_supported at submit time, before anything is queued.
Nano Banana series
Google’s image models — availability on each surface, parameters, and measured latency.
Choosing sync or async
Both surfaces exist and neither is deprecated.
Async is the better default for anything running behind a serverless function,
a reverse proxy, or a mobile client, because none of those reliably survive a
50-second request. Synchronous calls remain simpler for a script that just wants
bytes back.
Next steps
Nano Banana series
Parameter matrix, resolution tiers, and what differs between the two models.
Quickstart
The same flow end to end in about five minutes.