Reference
Plugin options, environment variables, endpoints, and exports for payload-mux in one place.
Every option, environment variable, endpoint, and export for @pro-laico/payload-mux.
Plugin options
muxVideoPlugin(options?) is the single entry point. One call registers the mux-video collection,
the upload + webhook endpoints, and the admin uploader. It's zero-config: every option falls back to a
MUX_* env var or a sensible default.
Pass options to customize. The plugin's own knobs live under options; the mux-video collection is
reshaped under collections.muxVideo (slug renames it, overrides is the Payload passthrough,
options its own knobs). The Reference tab is the interactive view (each group expands to its
nested fields); TypeScript is the same shape in code, every option at its default.
enabledbooleandefault trueWhen false, the plugin registers nothing: no collection, endpoints, or hooks.
collections{ muxVideo? }
The collections the plugin registers, one key each.
muxVideoCollectionOption<MuxVideoCollectionOptions>
The one collection the plugin registers — always registered, there is no false.
slugstringdefault 'mux-video'Rename it; the plugin follows the new slug everywhere — the webhook's lookup, ingestMuxVideo's default, and the muxVideoSlug on the marker.
overridesOmit<Partial<CollectionConfig>, 'slug'>Payload config merged onto the plugin's by the shared merge rules. Add your own fields under overrides.fields. Rename with the sibling slug key, not here. Don't redeclare a field the plugin injects (muxUploader, source, title, assetId, status, error, duration, posterTimestamp, aspectRatio, maxWidth, maxHeight, playbackOptions) — that's a named boot error.
optionsMuxVideoCollectionOptions
This collection's own knobs.
thumbnail'gif' | 'image' | 'none'default 'gif'List-view thumbnail style: animated gif, static image, or none.
optionsMuxOptions
The plugin's own domain knobs: credentials, upload / playback settings, and the access gates.
initSettingsMuxVideoInitSettingsdefault MUX_* env vars
Mux credentials and secrets. Every field is optional; an omitted field is read from its MUX_* env var (the plugin resolves these itself, which is what lets it accept the alias names below and warn at boot when a credential is missing). Pass a field only to override it (e.g. a non-standard env var name).
tokenIdstringdefault process.env.MUX_TOKEN_IDMux API token ID.
tokenSecretstringdefault process.env.MUX_TOKEN_SECRETMux API token secret.
webhookSecretstringdefault MUX_WEBHOOK_SECRET ?? MUX_WEBHOOK_SIGNING_SECRETSecret used to verify incoming Mux webhooks. Falls back to MUX_WEBHOOK_SIGNING_SECRET (the @oversightstudio/mux-video name) when the first is unset.
jwtSigningKeystringdefault MUX_SIGNING_KEY ?? MUX_JWT_KEY_IDJWT signing key ID, for signed playback. Falls back to MUX_JWT_KEY_ID.
jwtPrivateKeystringdefault MUX_PRIVATE_KEY ?? MUX_JWT_KEYJWT private key, for signed playback. Falls back to MUX_JWT_KEY.
uploadSettingsMuxVideoUploadSettings
Settings applied to every upload.
cors_originstringdefault process.env.NEXT_PUBLIC_SERVER_URL ?? '*'CORS origin for the direct-upload URL, usually your site URL. Resolves to options.uploadSettings.cors_origin ?? process.env.NEXT_PUBLIC_SERVER_URL ?? '*'.
new_asset_settingsMuxVideoNewAssetSettingsExtra new_asset_settings forwarded to Mux when the asset is created. Includes playback_policy; the options.playbackPolicy knob is the shorthand, and an explicit value here wins.
playbackPolicy'public' | 'signed'default 'public'Playback policy for newly uploaded videos. Shorthand for uploadSettings.new_asset_settings.playback_policy; set 'signed' (plus MUX_SIGNING_KEY / MUX_PRIVATE_KEY) for JWT-signed URLs.
accessMuxAccessOptions
Who may read videos and who may request an upload — one gate each. Both default to a logged-in admin-collection user. Create / update / delete fall back to Payload's collection access.
read(req) => boolean | Promise<boolean>default (req) => Boolean(req.user && req.user.collection === config.admin.user)Gates reads of the mux-video collection. Keep it closed under a signed playback policy: playback URLs are JWT-signed on read, so an anonymous read hands out a working signed URL.
upload(req) => boolean | Promise<boolean>default (req) => Boolean(req.user && req.user.collection === config.admin.user)Gates the direct-upload endpoints (POST / GET /mux/upload).
signedUrlOptions{ expiration?: string }default { expiration: '1d' }Lifetime of the JWT-signed playback / poster / gif URLs under a signed policy.
posterExtension'webp' | 'jpg' | 'png'default 'png'Image format for the poster (posterUrl).
animatedGifExtension'gif' | 'webp'default 'gif'Format for the animated preview (gifUrl).
autoCreateOnWebhookbooleandefault falseWhen true, the webhook backfills a Payload doc for an asset uploaded directly in Mux (on created / ready / updated for an asset Payload doesn't have yet). Off by default: one Mux account shared across dev / staging / prod would cross-backfill every environment's assets into the others.
import { muxVideoPlugin } from '@pro-laico/payload-mux'
// Every option at its default — this is the zero-config behaviour, written out.
muxVideoPlugin({
enabled: true,
collections: {
muxVideo: {
// slug: 'mux-video', // optional — renames the collection; the plugin follows the rename
// overrides: { /* … */ }, // optional — Payload CollectionConfig keys merged onto the plugin's
options: { thumbnail: 'gif' }, // list-view thumbnail: 'gif' | 'image' | 'none'
},
},
options: {
// initSettings: { /* … */ }, // optional, no default — all fields fall back to MUX_* env vars
// uploadSettings: { /* … */ }, // optional — cors_origin defaults to process.env.NEXT_PUBLIC_SERVER_URL ?? '*'
// access: { // both default to a logged-in admin user
// read: (req) => Boolean(req.user && req.user.collection === config.admin.user),
// upload: (req) => Boolean(req.user && req.user.collection === config.admin.user),
// },
playbackPolicy: 'public', // 'signed' issues JWT-signed URLs
signedUrlOptions: { expiration: '1d' },
posterExtension: 'png',
animatedGifExtension: 'gif',
autoCreateOnWebhook: false,
},
})Environment variables
The plugin and the Mux SDK read these automatically. Pass the matching initSettings / uploadSettings
option only to override a value or point at a non-standard variable name.
| Variable | Default | What |
|---|---|---|
MUX_TOKEN_ID | — | Mux API token ID. Required. |
MUX_TOKEN_SECRET | — | Mux API token secret. Required. |
MUX_WEBHOOK_SECRET | — | Verifies incoming Mux webhook signatures. Required for the webhook. Also accepts MUX_WEBHOOK_SIGNING_SECRET. |
MUX_SIGNING_KEY | — | JWT signing key ID. Required when playbackPolicy: 'signed'. Also accepts MUX_JWT_KEY_ID. |
MUX_PRIVATE_KEY | — | JWT private key. Required when playbackPolicy: 'signed'. Also accepts MUX_JWT_KEY. |
NEXT_PUBLIC_SERVER_URL | '*' | Your site URL — becomes the upload cors_origin. Falls back to '*' when unset. |
Migrating from @oversightstudio/mux-video? Keep your env as-is. The three names above where
the two plugins disagree — MUX_WEBHOOK_SIGNING_SECRET, MUX_JWT_KEY_ID, MUX_JWT_KEY — are
read as fallbacks, so nothing needs renaming. If both names are set, the Mux-SDK name wins.
Endpoints
The plugin registers three endpoints under Payload's API route. The upload pair is gated by the options.access.upload
option. See Endpoints & webhooks for the webhook
setup and what breaks without it.
| Endpoint | What it does |
|---|---|
POST /api/mux/upload | Mint a Mux direct-upload. The admin uploader posts files to it. |
GET /api/mux/upload?id=… | Read a direct-upload, to pick up its asset_id. |
POST /api/mux/webhook | Verify and apply Mux events: set metadata on ready/updated, delete on deleted, log on errored, and (with autoCreateOnWebhook) backfill assets uploaded in Mux. |
Exports
| Export | From | What |
|---|---|---|
muxVideoPlugin (default + named) | @pro-laico/payload-mux | The plugin factory. |
MuxVideoPluginOptions | @pro-laico/payload-mux | The plugin options type (for typing a wrapper / shared factory). |
MuxOptions, MuxVideoCollectionOptions | @pro-laico/payload-mux | The nested option groups: the plugin's own domain knobs (options) and the mux-video collection's own knobs (collections.muxVideo.options). |
readMuxMarker | @pro-laico/payload-mux | The typed view of config.custom.payloadMux: { options, muxVideoSlug, uploadPath, webhookPath }. The supported way to discover the managed slug — it follows collections.muxVideo.slug. Returns undefined when the plugin isn't registered. |
PayloadMuxMarker | @pro-laico/payload-mux | The marker's type. |
ingestMuxVideo | @pro-laico/payload-mux | Create a video doc from a local file / URL (seeding, imports, migrations). collection defaults to the slug on the marker, so a renamed collection needs no argument. |
IngestMuxVideoOptions | @pro-laico/payload-mux | Options for ingestMuxVideo: { source, title, playbackPolicy?, posterTimestamp?, collection? }. |
MuxAccessFn, MuxAccessOptions | @pro-laico/payload-mux | The access gate types, for factoring a shared read / upload gate out. |
MuxVideoInitSettings, MuxVideoUploadSettings, MuxVideoNewAssetSettings, MuxVideoSignedUrlOptions | @pro-laico/payload-mux | The nested settings types. |
MuxPlaybackPolicy, MuxPosterExtension, MuxAnimatedGifExtension, MuxAdminThumbnail | @pro-laico/payload-mux | The option value unions. |
MuxUploaderField | @pro-laico/payload-mux/components/MuxUploaderField | Admin uploader + player field (wired via the import map). |
MuxVideoGifCell | @pro-laico/payload-mux/components/MuxVideoGifCell | List-view animated-gif thumbnail cell (selected by collections.muxVideo.options.thumbnail). |
MuxVideoImageCell | @pro-laico/payload-mux/components/MuxVideoImageCell | List-view static-image thumbnail cell (selected by collections.muxVideo.options.thumbnail). |
Collections & globals
The plugin registers one collection, mux-video. Reshape it with collections.muxVideo — including
slug, which renames it and takes the plugin's own references with it. See
Using video for its playback fields and how to relate to it.
Next
- Use a video — relate, play back, and sign playback URLs.
- Endpoints and webhooks — the upload endpoints, the webhook, and server-side ingest.
- How it works — the asset lifecycle, revalidation, and seeding.
- Troubleshooting — videos stuck on "preparing", signed-playback 403s, and more.