Media
Generate images, video, and audio from a catalog of hosted models, and ask questions about media you supply — outputs arrive as signed artifact URLs.
Media is a CoreSpeed-hosted capability: no third-party account to connect, and
the same /mcp seam as everything else, so identity, organization holds,
API-key caps, activity recording, and capability visibility all apply. It has
two halves — generation from a catalog of more than a thousand image, video,
and audio models, and understanding, which answers a question about a video,
image, or audio file you point it at.
Eight tools
| Tool | Use it for |
|---|---|
media__list_models | Search the generation catalog with credit rates. No arguments returns the featured picks. |
media__get_model | One model's input schema, vendor, and current rate. Call it before generating. |
media__generate | Run a model. Waits inline up to wait_seconds, otherwise hands back a running job. |
media__get_result | A job's outcome: fresh signed URLs for a finished job, or its current status. |
media__list_jobs | This organization's recent jobs, running and finished. Receipts are kept about 30 days. |
media__cancel | Stop a running job. Canceled jobs are never charged. |
media__create_upload | Mint a one-use upload URL for a local or private file. |
media__understand | Ask a question about a video, image, or audio file and get a text answer. |
Generate: pick a model, then run it
search by name, kind (image · video · audio) or exact category
read input_schema and the structured price
files back inline, or a job_id that finishes server-side
input is validated against the model's own input_schema. Unknown top-level
keys are rejected — the schema's properties are the allowlist — and safety
parameters are policy, not input: whatever the caller sends for a safety*,
nsfw*, or moderation* key is discarded and the safe value is enforced on the
server. When the upstream model rejects an input anyway, its own validation
detail is returned to you, unbilled.
File-typed inputs accept three sources:
- a public
httpsURL fetchable without authentication; - a
cs_file_*upload handle frommedia__create_upload(below); - an
art_*artifact id from an earlier generation — so image → video chains stay entirely inside CoreSpeed.
A model needs a rate before it can run
price in the catalog is structured, and it is a rate, not a total:
{ "state": "priced", "credits_per_unit": 4, "unit": "image" }{ "state": "unavailable" } carries no rate fields and means there is no rate
right now. Generation is refused (pricing_unavailable, retryable) rather than
billed blind — retry shortly.
Long generations become jobs
wait_seconds (default 45, max 300) is the time budget for the whole call. The
server answers inside it, one of two ways:
{
"model": "fal-ai/flux/schnell",
"kind": "image",
"job_id": "job_…",
"status": "succeeded",
"assets": [
{
"id": "art_…",
"mimeType": "image/png",
"size": 1284021,
"uri": "https://api.corespeed.io/artifacts/…",
"expiresAt": "2026-09-10T14:02:11.000Z",
"width": 1024,
"height": 1024
}
]
}{ "job_id": "job_…", "status": "running", "model": "fal-ai/kling-video/v2" }A running job keeps going on the server for up to 60 minutes, then expires
unbilled. Collect it with media__get_result from any session — any agent in
the organization can pick up a job another one started — and pass
wait_seconds there to long-poll instead of spinning.
Three rules keep this from costing you twice:
- Do not set a client-side tool timeout equal to or below
wait_seconds. That kills the very reply carrying yourjob_id. Disable the timeout for this call, or set a backstop of at least twicewait_seconds. - If the client timed out anyway, nothing is lost. The newest entry in
media__list_jobsis your job. Do not resubmit. - Signed URLs expire after 12 hours. Call
media__get_resultagain for a fresh set; the stored artifact does not go anywhere.
Job states are running, succeeded, failed, canceled, and expired. A
terminal failure comes back as a tool-level error with generation_failed (or
the upstream's own code, and its reason when it gave one),
generation_canceled, or generation_expired; an unknown id answers
job_not_found.
Understand: ask about a file
media__understand takes a prompt and one media source — a public https
URL, a YouTube watch URL, or a cs_file_* upload handle. mime_type is
inferred from the URL extension or carried by the upload handle.
- Video can be windowed with
start_seconds/end_seconds.max_cost_creditsconverts a credit budget into a window at the per-second rate; it bounds the media input only, and an explicitend_secondsoverrides it. Video is sampled at one frame per second, so fast action between frames can be missed, and timestamps stated in the answer are not guaranteed exact. - Audio and images reject all three window parameters, because clipping cannot be enforced for them. The whole file is analysed up to the capability's context limit.
The result carries analyzed_seconds (an estimate — a paging hint, not a
duration), truncated when the answer was cut at the output limit, and usage
with the metered quantities the call settled for.
Upload a private file
For a file that only exists on local disk:
- Call
media__create_uploadwith the exactmime_typeandsize_bytes. The result includesfile_uri(acs_file_*handle),upload_url, thePUTmethod, the headers to send — includingAuthorization— andexpires_at. PUTthe raw bytes toupload_urlwith every returned header, within 10 minutes. The ticket is one-use, and the declared type and size are bound to it.- Use
file_uriwithmedia__understandor any file-typedmedia__generateinput. The handle stays valid for 48 hours.
Files up to 2 GB are accepted. A deployment edge may still reject a very large
body with HTTP 413; treat that as non-retryable for the deployment rather than
retrying the same upload.
Pricing and holds
- Generation is billed once, after success, at the model's rate times the
usage the upstream actually reports. For calls whose size is only known
afterwards, the final amount can differ from the rate card. Failures,
cancels, and expiries never charge. For expensive kinds — video especially —
check
media__get_modelfirst. - Understanding bills 0.5 credits per image (an oversized image counts as several), 12 credits per minute of video and 4.2 per minute of audio, both metered per second, plus about 1.1 credits per 100 answer tokens. The question itself is free. Failures never charge.
The live figures are in the tool descriptions your client shows from
tools/list and in each model's price. Every charge lands itemized in the
organization ledger; see Billing & credits. An organization
billing hold or suspension stops a media call before it runs — as an isError
result with payment_required or org_suspended — and API-key spend caps apply
the same way.
Inspect in the dashboard
Dashboard → Media shows everything the
organization generated. Running jobs finish server-side and land there whichever
agent started them. Turning the capability off in
Capability controls hides the media__* tools from
tools/list; stored artifacts and job receipts are unaffected.