Make a vertical Short clip with curl and jq: submit, poll, download
A 20-line shell script that asks Sume for an 8-second 9:16 clip at 1080p, polls the job, and saves short.mp4, matched to YouTube's Shorts page.

You can make a vertical Short clip with nothing but curl and jq: POST to https://api.sume.com/v1/videos with aspect_ratio: "9:16", read polling_url from the reply, loop until status is completed, then download unsigned_urls[0]. The script below does that in under 20 lines and asks for 1080p, which is the ceiling YouTube states for uploaded Shorts.
Two YouTube pages set the targets. Understand three-minute YouTube Shorts (read 2026-10-10) says a Short can be up to three minutes and must have a square or vertical aspect ratio. Get started creating YouTube Shorts (read 2026-10-10) says you can upload Short videos with a maximum resolution of 1080p. One clip from this script is 3 to 10 seconds, so it is a building block for a longer Short, not the whole thing.
The script
It uses Gemini Omni Flash 1.1 because the Sume docs list it at 3 to 10 seconds, 360p/720p/1080p/4K, in 16:9 or 9:16, with native synced audio. Set SUME_API_KEY in your environment first; the key is never written into the script.
set -euo pipefail
API=https://api.sume.com
AUTH="Authorization: Bearer $SUME_API_KEY"
job=$(curl -sS -X POST "$API/v1/videos" -H "$AUTH" \
-H "Content-Type: application/json" -H "Idempotency-Key: short-001" \
-d '{"model":"gemini-omni-flash-1.1","aspect_ratio":"9:16",
"resolution":"1080p","duration":8,
"prompt":"A barista pours latte art, close vertical shot, cafe sounds"}')
url=$(jq -r .polling_url <<<"$job")
while :; do
r=$(curl -sS "$url" -H "$AUTH")
s=$(jq -r .status <<<"$r")
[ "$s" = completed ] && break
case "$s" in failed|cancelled) jq -r '.error // .status' <<<"$r"; exit 1;; esac
sleep 15
done
curl -sS "$(jq -r '.unsigned_urls[0]' <<<"$r")" -H "$AUTH" -o short.mp4
jq '{status, cost: .usage.cost}' <<<"$r"Why each field is there
The Video Generation page says the surface follows the OpenRouter video API with a few Sume differences. Those differences decide what you can leave out of the request.
| Field | Value | Reason |
|---|---|---|
| model | gemini-omni-flash-1.1 | Lists 9:16 and 3 to 10 seconds |
| aspect_ratio | 9:16 | Vertical, accepted for Shorts |
| resolution | 1080p | Matches YouTube's 1080p upload ceiling |
| duration | 8 | Whole seconds, inside the model's range |
| Idempotency-Key | short-001 | A retry returns the original job |
| size / seed / provider.options | not sent | Sume returns 400 for these on v1 |
What can go wrong
Check the loop's exit paths. A job can end as failed or cancelled, and the script prints the error field and stops rather than polling forever. The docs say a video usually takes from 30 seconds to several minutes, so a 15-second sleep is fine for one clip; for a batch, move to the callback_url webhook instead of many pollers.
If you change the model, change the numbers with it. The docs give seedance-2.5 4 to 30 seconds and wan-3.0 2 to 30 seconds, so an 8-second request fits all three, but a 2-second request fits only Wan. Read GET /v1/videos/models before you hard-code a duration.
Billing is visible in the last line. The poll response carries usage.cost, and the docs say Sume reserves the provider list price times 1.25 at submit; the cost field is the billable amount.
Check the file before you upload it
Do not trust the request alone; read the result. Sume's Video inspect page describes a probe that reads one media.sume.com clip your workspace already owns and returns probe facts plus sample stills, without re-encoding the source. Import the file first with POST /v1/media-imports, then send its URL as video_url with an Idempotency-Key.
Use the probe to confirm what you asked for: a vertical frame, a duration close to 8 seconds, and an audio stream. Use the stills to look at the first frame, because the opening seconds are what a Shorts viewer sees first. If the probe shows something other than what you requested, fix the request and resubmit under a new idempotency key; reusing the old key replays the original job.
From one clip to a Short
YouTube allows up to three minutes, and this script yields up to 10 seconds, so a full-length Short is a stitching job. Sume's Timeline 1.0 page describes joining ordered video slots with one audio spine into a single MP4. Keep the render at 1080 by 1920 or below for YouTube. Plan the join before you generate: eight 8-second clips make 64 seconds, and 22 make 176 seconds, just under the three-minute ceiling. The 1080p ceiling on the YouTube page is why the script does not ask for 4K, even though the model lists it.
Sources
Related posts
More in Developers
- Node script for a 9:16 TikTok video: check the model, then submit
A Node 20 fetch script that confirms a Sume model lists 9:16 and your duration, submits one 12-second 720p job, and saves an MP4 that fits TikTok's API limits.
- Revoked a Sume API key and it still works? Up to 15 seconds
After you revoke a Sume API key, the API can keep accepting it for up to 15 seconds by default, because the key lookup is cached. What that means for a leak.
- Sume public_reason: generation_rejected vs temporary error
How Sume picks generation_rejected, temporary_generation_error or generation_failed on a failed job from the provider HTTP status and the retryable flag.
- Sume "Generation could not start": rejected request or outage
Generation could not start is the fallback when a provider rejects a submit. A 4xx gives generation_rejected_request; anything else gives submit_failed.
Written by Sume