Is there an asset library API for AI images and videos?
Sume has no folders or tags. Your library is completed jobs plus durable media.sume.com artifacts, which you list, label by Idempotency-Key, and download.

Sume has no folder-and-tag asset library for generated images and videos that I could find in the docs. What it gives you is three pieces you can build one from: completed jobs listed by GET /v1/jobs, durable media.sume.com artifacts on each result, and a separate sume assets set of commands for input files. Labelling is up to you, and the cleanest label is the Idempotency-Key you send on submit.
This post lays out what each piece holds and how to query it, so you can decide whether that is enough or whether you should mirror the files into your own storage.
What counts as an asset on Sume?
Completed jobs can include artifact objects: an id like artf_..., a url on media.sume.com, a type and a content_type. The API schema also carries size_bytes, width, height, duration_ms and checksum_sha256, each nullable. Sume mirrors generated outputs into Sume-owned URLs before exposing them, and the docs tell integrations to store the Sume URL, not the raw provider URL.
Separately, the CLI has sume assets list, get, create --source-url, upload-url, complete, download-url and download. These register or upload first-party input files when a workflow needs asset ids. For normal Image, Video and Avatar requests the docs say to prefer public HTTPS URLs and skip the asset lifecycle.
How do I list everything I generated?
GET /v1/jobs returns your workspace's jobs newest first, capped at 100 per page. Filters are type, status (the job lifecycle values), limit (1 to 100), scope, run_id and thread_id. When data.next_cursor is present, pass it back as starting_after. An unknown query parameter is a 400 unknown_parameter, not a silently unfiltered page, so a typo in a filter name fails loudly.
The docs make one more point worth keeping: do not read identity off array position, because newest-first is not your submission order once retries happen. Each row carries the idempotency_key it was created with, and that is the column to join your own labels on.
import os, requests
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
params = {"limit": 100, "status": "completed"}
rows = []
while True:
page = requests.get("https://api.sume.com/v1/jobs", headers=H, params=params)
page.raise_for_status()
data = page.json()["data"]
rows += data["jobs"]
if not data.get("next_cursor"):
break
params["starting_after"] = data["next_cursor"]
film = [j for j in rows if (j.get("idempotency_key") or "").startswith("film-42-")]
print(len(rows), "jobs;", len(film), "belong to film-42")How do I label assets so they are findable?
That prefix convention is the whole trick. It costs nothing, survives retries because a retried submit with the same key returns the original job, and it lets you rebuild an index from GET /v1/jobs if your own database is lost.
| Need | Where | Notes |
|---|---|---|
| Name a shot | Idempotency-Key at submit, e.g. film-42-shot-03-take-2 | Returned on each job row; a replay returns the original job |
| Group a film | Common key prefix, filtered client-side | The list API has no key or prefix filter in its documented query |
| Filter by kind | type query parameter | Read the exact type string from a row you already have |
| Find failed work | status query parameter | Uses the documented job status values |
| Store the file | media.sume.com artifact URL and artf_ id | Download what you need to keep; no retention period is documented |
| Record the recipe | Your own database row per job id | Prompt, model, input URLs and key are not browsable by folder |
Where is this approach weak?
There is no server-side search by prompt, no tags, no folders and no shared-collection permissions in the documented API. Listing is by job, so a film made of eight clips is eight rows you group yourself. A prefix filter happens on your side after paging, which is fine for thousands of jobs and clumsy for hundreds of thousands.
For files you want to keep, download them. The CLI does it in one line: sume jobs download <job_id> --output-dir ./out writes completed media artifacts to a directory, and sume jobs list --agent --json gives the same list from a terminal. For a mirror into your own bucket, loop over finished rows and copy each url.
If you need to bring outside media in, import it first (POST /v1/media-imports) or register it with sume assets create --source-url ...; the video tools that take a media.sume.com URL refuse off-host links. The post comparing flat asset libraries goes into that difference.
Sources
Related posts
More in Developers
- AI image model fallback in Python: try the next model on a 502
Image models launch and fail on different days. A Python loop that tries the next Sume model id on 502 or 503, stops on 400, and keeps the 202 job path intact.
- Claude Cost Report API: daily buckets by workspace vs Sume /v1/usage
Anthropic's cost_report endpoint returns USD cost in 1d buckets, groupable by workspace or description. Sume's /v1/usage sums one thread, run or job instead.
- Avatar catalog search: explore mode, seed and diversity
POST /v1/avatar-catalog/search browses reusable avatars. Omit the query for explore mode, pass a seed to keep the order stable, and set diversity from 0 to 1.
- Avatar catalog search returns few results: auto_expand explained
When an avatar catalog search is thin, Sume relaxes filters in a set order and lists them in relaxed_filters. Set auto_expand to false for strict matching.
Written by Sume