TypeScript: check 8:1 against /v1/images/models before you POST

A 20-line TypeScript guard that reads the aspect_ratio values for a Sume image model and refuses a ratio it does not list, instead of a 400 at request time.

3 min readSume
All posts

Sume rejects an image request that sets a parameter the model does not list with 400 unsupported_parameter, and Nano Banana Pro and sume/auto do not list 8:1. A TypeScript guard that reads supported_parameters.aspect_ratio.values first turns a mid-batch 400 into an immediate, readable error before any generation starts.

The guard

It fetches the catalog, finds the model row, and compares. In production, cache the list for a while instead of fetching it on every call.

const BASE = "https://api.sume.com";
const auth = { Authorization: `Bearer ${process.env.SUME_API_KEY}` };

async function listed(model: string): Promise<string[]> {
  const r = await fetch(`${BASE}/v1/images/models`, { headers: auth });
  if (!r.ok) throw new Error(`models ${r.status}`);
  const { data } = await r.json();
  const row = data.find((m: { id: string }) => m.id === model);
  return row?.supported_parameters?.aspect_ratio?.values ?? [];
}

export async function generate(model: string, ratio: string, prompt: string) {
  const ok = await listed(model);
  if (!ok.includes(ratio)) {
    throw new Error(`${model} does not list ${ratio}; it lists ${ok.join(", ")}`);
  }
  const r = await fetch(`${BASE}/v1/images`, {
    method: "POST",
    headers: { ...auth, "Content-Type": "application/json" },
    body: JSON.stringify({ model, prompt, aspect_ratio: ratio }),
  });
  return { status: r.status, body: await r.json() };
}

What it returns for common pairs

Guard outcome by model and ratio (read 2026-10-09)
ModelRatioGuard result
google/nano-banana-2.18:1Pass
google/nano-banana-pro8:1Throws, ratio not listed
google/nano-banana-2.14:5Pass
openai/gpt-image-2.54:1Throws, ratio not listed

Gotchas

  • sume/auto is not in the catalog list, so the guard returns an empty list for it. Skip the guard for Auto or special-case it.
  • The guard checks the ratio only. resolution, quality, and n have their own descriptors on the same row.
  • A 200 carries the image and usage.cost; a 202 carries the job envelope. Branch on status.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume