A reference for LLMs and AI coding agents that write code against the Mux API. Read this page first to get correct patterns for assets, uploads, Robots AI workflows, playback, and webhooks.
This guide is written for LLMs and AI coding agents. It contains everything you need to write working code against the Mux API on the first try.
Before designing a video workflow, check the prompt library. Match the user's intended outcome and fetch the relevant prompt. Each prompt includes questions to resolve, execution options, API guidance, and checks for one-off or recurring work. For example, the podcast clipping prompt covers building a clip-review application, processing an episode, or scheduling new episodes.
Read only the prompt that applies. If none fits, continue with the guides and API reference below. The human-readable library also links to related implementation guides.
The Mux CLI (@mux/cli) lets you manage Mux resources directly from the terminal. It is useful for quick operations, scripting, automation, and CI/CD pipelines.
Install:
npm install -g @mux/cli # global install
# or run directly without installing:
npx @mux/cli
# or install via Homebrew:
brew install muxinc/tap/muxAfter installing, authenticate with mux login or set MUX_TOKEN_ID and MUX_TOKEN_SECRET environment variables. Always pass --agent to optimize output for AI agents (includes JSON output).
Common commands:
| Command | What it does |
|---|---|
mux assets create --url URL | Create an asset from a URL |
mux assets create --upload ./video.mp4 | Upload a local file |
mux assets list | List assets |
mux assets get ${ASSET_ID} | Get asset details |
mux assets delete ${ASSET_ID} | Delete an asset |
mux live-streams create | Create a live stream |
mux uploads create | Create a direct upload URL |
mux sign ${PLAYBACK_ID} | Generate a signed playback URL |
Use --wait to block until an asset is ready:
mux assets create --url "https://example.com/video.mp4" --wait --agent--url ingests remote media, --upload uploads local media, and --file reads a JSON asset configuration rather than a video file.
For the full list of commands, see the CLI documentation.
video.asset.readyBefore you can make API calls, your user needs to set up a Mux account and provide you with API credentials.
robots:read to read jobs and robots:write to create them. Add Mux Data or System permissions only if your integration needs them.If an existing token lacks Robots permissions, create a replacement token with those permissions and update your stored credentials. Enabling Robots for an organization does not add permissions to existing tokens. If the API says Robots is not enabled, an organization admin should follow the dashboard link in that error to complete enablement.
Store the credentials as environment variables:
MUX_TOKEN_ID=your-token-id
MUX_TOKEN_SECRET=your-token-secretFor details on how authentication works, see the make API requests guide.
Never expose API credentials in client-side code. All Mux API calls must be made from a server.
This is for when you have a small, constrained number of videos — a hero video or background video on your homepage, a demo reel, or a few dozen videos across your site. The key characteristic is that the set of videos doesn't change often and is manageable enough to hardcode.
In this case, you can hardcode playback IDs directly in your code or extract them into a JSON config file with metadata:
{
"videos": [
{ "title": "Hero Video", "playbackId": "TXjw00EgPBPS6acv7gBUEJ14PEr5XNWOe" },
{ "title": "Product Demo", "playbackId": "a4nOgR00sKz6cMWLeM5skT8ePBn7U6gC5" }
]
}Then use Mux Player to embed each video:
import MuxPlayer from '@mux/mux-player-react';
<MuxPlayer playbackId="TXjw00EgPBPS6acv7gBUEJ14PEr5XNWOe" />To create your assets and get playback IDs, use the CLI (mux assets create --url URL --wait --json) or the stream video files guide.
This is for when videos are uploaded dynamically as part of your application. Common scenarios include:
For these use cases, you will need to:
video.asset.ready), when it errors, or when it's deletedFor AI features, use Mux Robots when a built-in managed workflow fits. Choose @mux/ai when you need custom models, prompts, or video-processing logic. A direct transcript + LLM call can fit a narrow text-only task if you own its retries, validation, and provider costs. See the AI decision table for examples and responsibilities.
Official server-side SDKs:
Mux Robots runs managed AI workflows against existing Mux assets. For example, use it to summarize videos, moderate uploads, generate chapters, or translate captions. See the full workflow catalog for all available workflows. Mux handles model selection, execution, and job status; you do not need separate AI-provider keys.
Before starting a job:
ready. Use its asset ID, not its playback ID.robots:write to create jobs and robots:read to retrieve them. Creating or managing the asset also needs the appropriate Mux Video permissions. If Robots is not enabled for the organization, an admin must follow the dashboard link in the API's permission error.This server-side example uses @mux/ts version 16 or later, where mux.robots calls /robots/v1. Install it with npm install @mux/ts@^16. Set MUX_TOKEN_ID, MUX_TOKEN_SECRET, and MUX_ASSET_ID for a ready asset in the same environment. The token also needs video:read for the asset-readiness check. See the TypeScript SDK migration guide for older integrations.
import Mux from '@mux/ts';
const mux = new Mux();
const assetId = process.env.MUX_ASSET_ID;
if (!assetId) throw new Error('Set MUX_ASSET_ID to a ready Mux asset ID');
const asset = await mux.video.assets.retrieve(assetId);
if (asset.status !== 'ready') throw new Error('Wait for the asset to be ready');
let job = await mux.robots.jobs.summarize.create({
parameters: { asset_id: assetId },
});
console.log({ job_id: job.id, workflow: job.workflow });
const deadline = Date.now() + 15 * 60 * 1000;
while (job.status === 'pending' || job.status === 'processing') {
if (Date.now() >= deadline) {
throw new Error('Polling timed out; retrieve job ' + job.id + ' later');
}
await new Promise(resolve => setTimeout(resolve, 3000));
job = await mux.robots.jobs.summarize.retrieve(job.id);
}
if (job.status !== 'completed' || !job.outputs) {
throw new Error('Job ' + job.id + ': ' + JSON.stringify(job.errors ?? job.status));
}
console.log(job.outputs);Save both the job ID and workflow name so you can resume with the matching retrieve method. Read outputs only after completed; handle errored and cancelled as terminal outcomes. A polling timeout does not cancel the job, so retrieve it later instead of creating a duplicate.
For production integrations, use Robots webhooks such as robots.v1.job.summarize.completed; the completed event includes the full job in data. Persist outputs your application needs: jobs are deleted after 30 days. Use Directives to run dependent workflows or automate them on new uploads. See the Robots API reference for supported job operations and the individual guides for prerequisites and costs.
Unless the user specifies otherwise, use these values:
| Parameter | Default to use | Notes |
|---|---|---|
playback_policies | ["public"] | Use "signed" only if the user needs secure/private playback |
video_quality | "basic" | No encoding costs and great for most use cases. Use "plus" if the user needs higher quality encoding |
static_renditions | Do not set | Only set if the user explicitly needs downloadable MP4/M4A files. See the static renditions guide |
max_resolution_tier | Do not set | Defaults to 1080p. Set to "2160p" only if the user requests 4K |
playback_policies: "public" allows open access. Use "signed" for secure video playback with signed JWTs.video_quality: See pricing for the difference between "basic" and "plus".static_renditions: Replaces the deprecated mp4_support parameter. Use [{ "resolution": "highest" }] for an MP4 download or [{ "resolution": "audio-only" }] for an M4A file. See the static renditions guide for all options.After creating an asset, save the relevant data into your database or persistence layer. At minimum, store the asset ID and playback ID. You will also want to save metadata as it becomes available: status, duration, aspect_ratio, resolution_tier, and any static_renditions information.
For simple integrations with a fixed set of videos — hero videos, background videos, demo reels on a marketing site — you can hardcode playback IDs in a JSON file or config object. These rarely change and don't need a database.
For production applications where users upload videos, videos are created programmatically, or the video catalog changes over time, always persist asset data in a database. Use webhooks to keep your database in sync — listen for video.asset.ready to update status, and video.asset.deleted to clean up records.
| ID type | What it's for |
|---|---|
| Asset ID | Managing the asset (get, update, delete) via api.mux.com |
| Playback ID | Streaming the video via stream.mux.com |
| Upload ID | Tracking direct upload status |
| Stream Key | Broadcasting to a live stream (keep secret) |
| Live Stream ID | Managing the live stream via api.mux.com |
Check AI workflow prerequisites before queueing jobs. Use the Robots prerequisites matrix to distinguish required subtitle tracks from recommended context. A ready asset can still have preparing subtitle tracks.
Do NOT confuse Asset IDs with Playback IDs. Asset IDs are for API operations (api.mux.com). Playback IDs are for streaming (stream.mux.com). They are different strings.
Do NOT use the playback URL before the asset is ready. Always check status === "ready" first. A playback URL for a preparing asset will not work.
Do NOT construct playback URLs with the Asset ID. The correct URL is https://stream.mux.com/{PLAYBACK_ID}.m3u8, not https://stream.mux.com/{ASSET_ID}.m3u8.
Do NOT expose API keys in client-side code. API credentials (Token ID and Token Secret) must never be included in frontend JavaScript, mobile apps, or any code that runs on the user's device. All Mux API requests must be made from a trusted server.
Do NOT expose stream keys in client-side code. Stream keys allow anyone to broadcast to your live stream. Keep them server-side only.
Do NOT hardcode playback URLs. Always construct them from the playback ID returned by the API.
Do NOT poll more than once per second. The API has rate limits. Poll every 2 seconds for asset status.
Do NOT use POST endpoints at high volume without backoff. POST requests are rate limited to ~1 request per second sustained. GET requests allow ~5 per second.