Create an AI video workflow via API: a Sume Format and its SKILL.md
Create a Sume Format with POST /v1/formats, then write its SKILL.md recipe through the Contents API. The fields, the slug rules, and the errors to handle.

To create an AI video workflow over the Sume API, send POST /v1/formats with a slug. That opens a new Format in your API key's workspace with a minimal SKILL.md, and you then replace that file with your recipe through the Contents API. Your backend calls the result at POST /v1/formats/{handle}/{slug}/runs.
A Format is a saved recipe that a backend calls by name; What is a Sume Format? covers authoring one in chat instead. The facts below come from Editing a Format package, the Format API page, and the Sume API reference, read on 2026-09-26.
Which workspace does a new Format belong to?
The one your key belongs to. POST /v1/formats needs formats:write, and it has no {handle} in the address, so there is no way to create a Format in somebody else's workspace. A team key creates a team Format that answers at the workspace's handle; a personal key creates one at your own handle.
A key without formats:write gets 403 insufficient_scope. Scopes cannot be patched onto a key, so mint a new one that carries it. Service-account keys get the same 403: they cannot create or edit packages.
Which fields does POST /v1/formats take?
The body describes the Format, not its files. Package files go through the Contents API, so they follow one set of rules no matter who wrote them.
| Field | Rules |
|---|---|
slug | Required. 1–64 characters, lowercase, matching ^[a-z0-9][a-z0-9._-]*$. Unique within your workspace; it is the {slug} half of the Format's address. |
title | Up to 80 characters. The display name in the Formats library. Defaults to the slug. |
description | Up to 1024 characters, one line only. Written into the seed SKILL.md frontmatter, which the catalog reads the description back from. Defaults to a placeholder. |
auto_init | Defaults to true and commits a minimal valid SKILL.md. false is a 400: every package must contain SKILL.md, so there is no empty Format. |
How do I create a Format and write its recipe?
Three calls. The create answers 201 with the new Format: its skl_… id, handle, slug, version, package_sha, contents_url, and vanity_invoke_url. Keep package_sha and contents_url: the first is the If-Match precondition for your next write, the second is where to send it. Replacing the seed SKILL.md is the intended next call, and because that file already exists, the replace needs its blob sha from a read.
# 1. Open the Format in your key's workspace
curl -sS -X POST "https://api.sume.com/v1/formats" \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-d '{"slug":"plate-shots","title":"Plate shots","description":"Studio plate photography."}'
# 2. Read the seed SKILL.md for its sha
curl -sS "https://api.sume.com/v1/formats/acme/plate-shots/contents/SKILL.md" \
-H "Authorization: Bearer $SUME_API_KEY"
# 3. Replace it: content is the whole new file, base64-encoded
curl -sS -X PUT "https://api.sume.com/v1/formats/acme/plate-shots/contents/SKILL.md" \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "If-Match: $PACKAGE_SHA" \
-H "Content-Type: application/json" \
-d '{"message": "write the recipe", "content": "LS0tCm5hbWU6IHBsYXRlLXNob3Rz…", "sha": "0ee8…"}'What must the Format package contain?
The package rules are checked before anything is committed, and a rejected package commits nothing. The ones a first write meets:
SKILL.mdsits at the package root, and its frontmatternamemust equal the Format's slug.- Other files live at the root or one directory deep under
references/oragents/, as.md,.json,.yaml,.yml, or.txt. - A rejected path answers
skill_path_invalidand spells the whole allowlist back, so one rejection is enough to fix the name. - Each write returns the new
commit.tree.sha(the nextIf-Matchvalue) andversion. Edit Sume Format files with If-Match covers multi-file commits, and how to write a SKILL.md recipe covers what goes in it.
Which errors can the create return?
The first four are on the docs pages. The last two are current behavior that the docs pages do not list.
409 skill_slug_taken: your workspace already has a Format with that slug. Creating never overwrites; pick another.409 skill_slug_reserved: a Format by Sume holds that slug globally.503 format_git_unavailable: package history could not be opened. The repository is opened before the catalog row, so no Format was created.403 insufficient_scope: the key lacksformats:write, or it is a service-account key.400 skill_slug_invalidfor the reserved slugsruns,bulk-runs, andgrants, which would collide with API routes.400 skill_limit_exceededwhen the user who owns the key already owns 50 custom Formats. The cap counts that user's Formats, not the workspace's.
Can I start from an existing Format instead?
Yes. Fork a Format by Sume in the Format library when you want to change one; your copy is addressed as {your_handle}/{slug}. You can also author a Format in the Agents dashboard or in chat.
However it was made, call it with POST /v1/formats/{handle}/{slug}/runs. A Format you have never run over the API may read status: inactive and api_trigger_enabled: false until its first run, and still runs, so do not gate your integration on those fields.
Sources
Related posts
Written by Sume