Unity editor tool: generate an AI video clip with UnityWebRequest
A Unity coroutine posts a Wan 3.0 job to Sume, polls /v1/jobs/{id}/status with next_poll_after_seconds and downloads the MP4 with DownloadHandlerFile.

In Unity, generate a placeholder cutscene clip from an editor script or a build-pipeline tool with a coroutine: UnityWebRequest.Post to https://api.sume.com/v1/videos, then UnityWebRequest.Get on /v1/jobs/{id}/status every few seconds, then a download with DownloadHandlerFile. Sume answers the submit with 202 and a job id; the status response says when to read again through next_poll_after_seconds (Sume jobs guide, read 2026-10-06).
Keep the API key out of anything you ship. A key inside a player build can be extracted, so this belongs in editor tooling or on your own server. The clip is wan-3.0, 5 seconds, 720p, $0.625 at Sume's $0.125 per second.
What does the MonoBehaviour look like?
JsonUtility needs serializable classes, so the two small ones below mirror the fields we read. An absent next_poll_after_seconds parses as 0, which the code replaces with 15. Needs Unity 2022.2 or newer for the string-body Post overload.
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
[System.Serializable] class Job { public string id; }
[System.Serializable] class St { public bool terminal; public string sume_status; public int next_poll_after_seconds; }
public class SumeClip : MonoBehaviour {
const string Api = "https://api.sume.com";
void Auth(UnityWebRequest r) =>
r.SetRequestHeader("Authorization", "Bearer " + System.Environment.GetEnvironmentVariable("SUME_API_KEY"));
IEnumerator Start() {
string json = "{\"model\":\"wan-3.0\",\"prompt\":\"Fog over a pixel-art harbor\",\"duration\":5,\"resolution\":\"720p\"}";
using var post = UnityWebRequest.Post(Api + "/v1/videos", json, "application/json");
Auth(post); post.SetRequestHeader("Idempotency-Key", "unity-harbor-001");
yield return post.SendWebRequest();
if (post.result != UnityWebRequest.Result.Success) { Debug.LogError(post.downloadHandler.text); yield break; }
string id = JsonUtility.FromJson<Job>(post.downloadHandler.text).id;
for (int i = 0; i < 120; i++) {
yield return new WaitForSeconds(15);
using var get = UnityWebRequest.Get(Api + "/v1/jobs/" + id + "/status");
Auth(get); yield return get.SendWebRequest();
var s = JsonUtility.FromJson<St>(get.downloadHandler.text);
if (!s.terminal) continue;
if (s.sume_status != "completed") { Debug.LogError(s.sume_status); yield break; }
using var dl = UnityWebRequest.Get(Api + "/v1/videos/" + id + "/content?index=0");
Auth(dl); dl.downloadHandler = new DownloadHandlerFile(Application.dataPath + "/clip.mp4");
yield return dl.SendWebRequest(); yield break;
}
}
}Does the clip play in the editor right away?
Unity's VideoPlayer takes a file path or URL, so point it at the saved clip.mp4 after the download finishes. The content endpoint needs the Authorization header, which is why the download goes through UnityWebRequest instead of giving a bare URL to the player. Check your target platform's supported codecs before you plan on playing it in a build.
Does re-running the script bill a second clip?
It can if you re-run the submit step. Send a stable Idempotency-Key on POST /v1/videos (here a fixed string; in practice a row id) so a repeat returns the original job. A give-up on the client never cancels the render, so keep the job id and read it again (Sume jobs guide, read 2026-10-06).
Sources
Related posts
More in Developers
- Uptime monitor for the Sume API: probe GET /v1/me, spend reads
A 30 second probe of GET /v1/me costs two reads a minute against a 4,800 read Free budget. Python probe and a status table for 401, 429 and 5xx.
- What did one transcription job cost? GET /v1/usage by job_id
Read GET /v1/usage?job_id= and sum data.summary.debited_usd_micros to see what one Sume STT job really cost. Holds and refunds are not counted as spend.
- User closed the tab mid-render: cancel the Sume job or let it finish?
Cancel works only before generation starts; after that you get 409 job_generation_already_started and the job bills. A tested tab-close handler.
- Verify a Sume TTS transcript_receipt SHA-256 yourself in Python
Recompute submitted_transcript_sha256 from your script with NFC and LF canonicalization and compare it to the transcript_receipt on a finished Sume TTS job.
Written by Sume