After imagen-4.0-generate-001: read n from endpoints, use webhook mode
Do not assume your old image count carries over. Read supported_parameters.n from the Sume endpoints route, then submit in webhook mode and wait for.

Ask the model's endpoints route how many images one request may return, cap your n at that, and send the request with mode: "webhook" so the images arrive on job.completed. Google shut down imagen-4.0-generate-001 on August 17, 2026 and points to gemini-nano-banana-2.1, and nothing guarantees the replacement takes the same per-request count as your old code assumed.
Where the number lives
Sume's image docs show each endpoint record with supported_parameters. n appears there as a range with min and max; the docs' example uses 1 to 4 for one model, which is an example, not a promise for yours. Read it for the id you call.
| Question | Route | Field |
|---|---|---|
| Which models exist | GET /v1/images/models | data[].id |
| How many images per call | GET /v1/images/models/{id}/endpoints | supported_parameters.n.max |
| What it costs | same endpoints route | pricing lines |
| Which ratios and sizes | same endpoints route | supported_parameters |
The submit
mode: "webhook" with a webhook_url makes /v1/images answer 202 with the job envelope; the images come later as artifacts in the job.completed payload. The webhook_url must be public HTTPS; localhost and private addresses are rejected. The sample prints the status and the cap it used.
Webhook delivery makes up to 10 attempts at 30-second spacing and can repeat, so dedupe on job_id. Keep a poll of status_url as a fallback for a missed delivery.
const base = process.env.SUME_BASE ?? "https://api.sume.com";
const headers = { Authorization: `Bearer ${process.env.SUME_API_KEY}`, "Content-Type": "application/json" };
const model = "google/nano-banana-2.1";
const meta = await (await fetch(`${base}/v1/images/models/${model}/endpoints`, { headers })).json();
const nMax = meta.endpoints[0].supported_parameters.n?.max ?? 1; // read it; do not assume Imagen's old count
const res = await fetch(`${base}/v1/images`, {
method: "POST",
headers: { ...headers, "Idempotency-Key": "catalog-shoot-0042" },
body: JSON.stringify({ model, prompt: "ceramic mug on oak table", n: Math.min(4, nMax), mode: "webhook", webhook_url: "https://hooks.example.com/sume" }),
});
console.log(res.status, nMax); // 202 with the job envelope; the images arrive via job.completedWhat this skips
The sample does not verify a signature, because it only sends; your receiver must check x-sume-webhook-signature before it trusts the body. It also uses a placeholder hook host, so swap in your own. A big n at high quality can exceed the 30-second wait in sync mode, which is the reason to go async here rather than hold an HTTP request open.
Sources
Related posts
More in Developers
- Alt text for a 30-image gallery in one Sume Agent Completion
One Agent Completion call can take up to 30 images and return an alts array under an object schema. Python stdlib script with the cap, poll and limits.
- API key scopes for Sume: which key can call which endpoint family?
Sume API keys carry fixed scopes: formats:write, actions:read, agent_completions:write, account:read. Which scope each route needs, and why old keys get a 403.
- Arabic speech to text API: Sume STT with language_code ar
Transcribe Arabic audio with Sume STT: send language_code ar, check the reported language, and review the text. $0.01 per audio minute.
- Avatar job tracking table: which Sume ids to store and why
Avatar work produces a handle, a job id, a preview id and a video id. A small SQL table that keeps them straight, plus the status fields to poll.
Written by Sume