make -j4 as a resumable Wan 3.0 batch runner with an Idempotency-Key
Twelve Wan 3.0 shots as twelve make targets. Re-run after a crash and only missing outputs submit, with an Idempotency-Key per shot. Tested on a stub server.

make already knows how to run jobs in parallel (-j4), skip finished work (the output file exists) and stop on failure. That is a resumable batch runner with no code. Each shot is a target out/shot-NN.json whose recipe posts one Wan 3.0 job and keeps the response.
Two details make it safe. The response is written to $@.part and moved into place only on success, so a failed curl never leaves a file that looks finished. And the Idempotency-Key is trailer-v5-shot-$*, so if a request was accepted but the response was lost, re-running replays the original job and does not submit a second. A key reused with a different body returns 409 idempotency_conflict; change the v5 part of the key when the prompts change.
The Makefile
Recipe lines must start with a tab. Run SUME_BASE=https://api.sume.com SUME_API_KEY=... make -j4. Each 5-second 480p clip is $0.3125 on Sume, so the 12 shots are $3.75. On a local stand-in server, make -j4 printed twelve acceptances; after deleting two output files, a re-run built only those two.
SHOTS := 01 02 03 04 05 06 07 08 09 10 11 12
OUT := $(SHOTS:%=out/shot-%.json)
all: $(OUT)
out/shot-%.json:
@mkdir -p out
@curl -sf -o $@.part -X POST "$(SUME_BASE)/v1/videos" \
-H "x-api-key: $(SUME_API_KEY)" -H "content-type: application/json" \
-H "Idempotency-Key: trailer-v5-shot-$*" \
-d "{\"model\":\"wan-3.0\",\"prompt\":\"shot $*\",\"duration\":5,\"resolution\":\"480p\"}" \
&& mv $@.part $@ && echo "shot $* accepted"Mind the plan limits
-j4 is four concurrent submits, not four concurrent renders. A Pro workspace processes 4 jobs, queues 20, and accepts 24 in total; a submit beyond that gets 429 queue_full. Pick -j to stay well under your plan's accepted capacity, and see the pacing post for the budget numbers. On a hard stop such as 402, curl -f fails the target and make halts, which is what you want.
The target here only records acceptance. Add a second rule that polls GET /v1/videos/{id} and downloads the file once the status is completed.
Sources
Related posts
More in Developers
- Mandarin Chinese speech to text API: Sume STT language_code zh
Transcribe Mandarin audio with Sume STT using language_code zh, then check the result and timings. $0.01 per audio minute and no accuracy claim without a test.
- mask_url on ChatGPT Image 2: not listed, only the 2.5 rows take it
Sume lists mask_url only on ChatGPT Image 2.5 Flare and Sunburst. Sending it to ChatGPT Image 2 is rejected. What to do for a masked edit on the older row.
- MCP outputSchema vs Sume output_schema: who sets the contract
In MCP the server declares a tool's outputSchema. In a Sume Agent Completion you send output_schema per run, and the result can still come back degraded.
- MCP tool-name rules (2025-11-25): do Sume's tool ids comply?
The MCP 2025-11-25 spec says tool names should be 1-128 characters from A-Z, a-z, 0-9, underscore, hyphen and dot. Sume's longest documented id is 36.
Written by Sume