OpenRouter video payload on Sume: drop seed, size, provider.options

Sume /v1/videos follows the OpenRouter shape but rejects seed, size and provider.options with a 400. A Node function that strips them and checks the model id.

5 min readSume
All posts

A client written for the OpenRouter video API works on Sume after you change the base URL and key, with a short list of exceptions. Three request fields are rejected with 400: seed, size, and a non-empty provider.options. The model id must also be a bare Sume catalog id, not an org/slug id. The Node function below removes the three fields, reports what it removed, and throws when the model is not in your list of Sume ids.

What differs

Sume's /v1/videos reference says it agrees field-for-field with OpenRouter's video generation guide, and then lists the exceptions in one table. The rows that change a request body are these.

Request differences between OpenRouter and Sume /v1/videos (Sume docs, read 2026-10-09)
AreaOpenRouterSume
Base URLhttps://openrouter.ai/api/v1/videoshttps://api.sume.com/v1/videos
Model idsorg/slugBare catalog ids such as seedance-2
sizeAccepted when the model lists supported_sizesEvery v1 model reports supported_sizes null, so 400 unsupported_parameter; use resolution plus aspect_ratio
provider.optionsForwarded to the matched providerNon-empty value returns 400 unsupported_parameter
seedMany models accept itNo v1 model accepts it; each reports seed false
IdempotencyNone on this routeIdempotency-Key header; a replay returns the original job

The function

forSume destructures seed, size and provider away from the body, and records a note for each one that was present. An empty provider object, or one with empty options, is allowed. The model check runs after the destructuring, so a wrong id fails before any network call.

Silent dropping hides a real change: a seeded request was asking for repeatable output, and Sume cannot promise it. Log the notes. If your product depends on seeds, run those jobs elsewhere rather than pretending the field was honored.

The demo call sends wan-3.0 for 8 seconds with all three bad fields, so it prints a body without them and a dropped list with three entries. Without the function, the same request would come back as a 400 whose error envelope names the field and carries a request_id, which is fine in a test and wasteful in production, because every rejected call still uses a write from your per-minute budget.

export function forSume(body, listedIds) {
  const { seed, size, provider, ...rest } = body;
  const dropped = [];
  if (seed !== undefined) dropped.push("seed");
  if (size !== undefined) dropped.push("size (use resolution + aspect_ratio)");
  if (provider && Object.keys(provider.options ?? {}).length) dropped.push("provider.options");
  if (!listedIds.includes(rest.model)) {
    throw new Error(`${rest.model} is not in GET /v1/videos/models; pick a listed bare id`);
  }
  return { body: rest, dropped };
}

const listed = ["seedance-2.5", "wan-3.0", "minimax-h3", "gemini-omni-flash-1.1"];
const out = forSume(
  {
    model: "wan-3.0",
    prompt: "A kite over a dune",
    seed: 42,
    size: "1280x720",
    provider: { options: { foo: 1 } },
    duration: 8,
  },
  listed,
);
console.log(out);

What to do about size

size looks harmless because 1280x720 is the same shape as 720p at 16:9. Sume does not translate it. Pick resolution (480p, 720p, 1080p and so on, from supported_resolutions) and aspect_ratio from the model's lists. For a 1280x720 intent send resolution 720p with aspect_ratio 16:9.

After the body, check the rest of your client. Webhooks use Sume's own job envelope with x-sume-webhook-signature, not video.generation events. Billing is the workspace USD balance rather than credits, and usage.cost is the amount billed.

Finally, test the ported client against GET /v1/videos/models rather than against a recorded fixture. The list endpoint tells you which ids exist today, and the function above will throw for any id that is not in it. That one check catches both a typo and a model Sume does not list.

  • Call GET /v1/videos/models and pass the ids to forSume.
  • Fail on unknown models rather than guessing a provider.
  • Replace any OpenRouter signature check before you move webhooks.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume