AppleScript: submit a Wan 3.0 video job and save it to the Desktop
A 22-line AppleScript that runs curl and jq through do shell script, polls a Sume video job and saves the MP4 to the Desktop. A 2 s 480p Wan 3.0 clip is $0.125.

Some Mac workflows never leave Script Editor: a folder action, a Keyboard Maestro macro, an Automator step. For those, the shortest path to the Sume video API is not a library but do shell script, which runs curl and jq and hands back the output as text. macOS ships both tools, so a 22-line AppleScript can submit a job, wait for it and save the clip.
The script requests a 2-second, 480p Wan 3.0 clip. Wan 3.0 at 480p is $0.0625 a second on Sume, so this test job costs $0.125. It was run against a local stand-in server that returns the documented 202, poll and 302 shapes, with the base URL and output path swapped for the test.
The script
Run it with osascript video.applescript from Terminal with SUME_API_KEY exported. It reads the key with system attribute, which sees the environment of the process that launched it. An app started from Finder or Spotlight does not see variables from your shell profile, so for a double-clickable app put the key in a file with restricted permissions and read it there.
set apiBase to "https://api.sume.com"
set apiKey to (system attribute "SUME_API_KEY")
set pollSeconds to 30
try
set pollSeconds to (system attribute "POLL_SECONDS") as integer
end try
set auth to "-H " & quoted form of ("Authorization: Bearer " & apiKey)
set body to "{\"model\":\"wan-3.0\",\"prompt\":\"Steam rising from a coffee cup\",\"duration\":2,\"resolution\":\"480p\"}"
set submitCmd to "curl -sS " & apiBase & "/v1/videos " & auth & " -H 'Content-Type: application/json' -d " & quoted form of body
set pollUrl to do shell script submitCmd & " | jq -er .polling_url"
repeat
delay pollSeconds
set job to do shell script "curl -sS " & quoted form of pollUrl & " " & auth
set jobState to do shell script "jq -r .status <<< " & quoted form of job
if jobState is in {"failed", "cancelled"} then error jobState
if jobState is "completed" then
set videoUrl to do shell script "jq -r '.unsigned_urls[0]' <<< " & quoted form of job
do shell script "curl -sSL " & quoted form of videoUrl & " " & auth & " -o ~/Desktop/sume-clip.mp4"
display notification "Saved ~/Desktop/sume-clip.mp4" with title "Sume video"
exit repeat
end if
end repeatDetails worth knowing
The pattern is the same as every other language on this API; only the quoting is different.
quoted form ofwraps each value for the shell. Use it for the JSON body, the polling URL and the artifact URL, because a prompt with an apostrophe would otherwise end the command early.jq -er .polling_urlfails on a missing field, which makes the AppleScript raise an error instead of polling an empty URL.- The artifact download uses
curl -Lto follow the redirect from/v1/videos/{id}/content?index=0. delayblocks the script for 30 seconds by default between polls. SetPOLL_SECONDS=0only against a test server.
Cost of experimenting
Because the price is by the second and resolution, the table shows how quickly a test grows if you change the two numbers in the JSON body. Wan 3.0 takes 2 to 30 seconds.
| Clip | 480p | 720p | 1080p |
|---|---|---|---|
| 2 s | $0.125 | $0.25 | $0.50 |
| 5 s | $0.3125 | $0.625 | $1.25 |
| 10 s | $0.625 | $1.25 | $2.50 |
Next steps
Add an Idempotency-Key header to the submit command if the script can be run twice by a macro, so a retry returns the first job instead of charging again. Show display notification on failure as well, with the job error, and keep the job id in a text file before polling begins.
Sources
Related posts
More in Developers
- Ask a decision model to approve a Sume dry_run estimate before paying
Call the paid MCP tool with dry_run true, hand the estimate to a yes/no decision, and only then send idempotency_key with a max_spend_usd that you set.
- Entity error 14.41%? Score your own call audio with Sume STT in Python
AssemblyAI reports 14.41% entity error on voice-agent audio and 3.44% English WER. Neither is yours. Compute entity recall on 20 of your clips with Sume STT.
- AssemblyAI word boost cuts name errors 61%: a term map for Sume STT
AssemblyAI reports word boost cut entity errors 60.9% on names and 72.8% on technical terms. Sume STT has no boost field; here is a post-correction map.
- Assign a Sume video model to each old prompt by clip length
A short Python planner that reads a CSV of old prompt lengths, sends 10 seconds or less to Omni, up to 30 seconds to Wan 3.0, and splits longer clips.
Written by Sume