Endpoints & webhooks
Finish long-encoding videos, sync Mux-dashboard deletes, and ingest video in code — the endpoints and webhook that keep Payload and Mux in step.
The plugin mounts three HTTP endpoints and expects one Mux webhook. Together they finish slow-encoding videos, mirror Mux-dashboard deletes back into Payload, and let you create a video entirely in code.
Endpoints
The plugin registers three endpoints under Payload's API route. The upload pair is gated by the options.access.upload option.
| 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. |
Webhook
On upload, the beforeChange hook polls the new asset for ~6 seconds. If Mux finishes encoding in that window, the hook fills in the playback metadata inline. Anything slower is saved with just its assetId and left for the webhook.
Point a Mux webhook at /api/mux/webhook (or <your routes.api>/mux/webhook if you've customized Payload's API route). Set MUX_WEBHOOK_SECRET so the plugin can verify each event's signature.
The webhook needs a publicly reachable URL. Mux pushes events to your endpoint, so its servers
must be able to POST to it. The SDK only verifies the signature on receipt — it can't make Mux reach
localhost. In production, set MUX_WEBHOOK_SECRET and point the dashboard at
https://your-site/api/mux/webhook. For local dev, expose localhost with a tunnel
(cloudflared tunnel --url http://localhost:3000 or ngrok) and set that URL as the webhook.
Not every flow depends on the webhook. Use the split below to know what breaks without it.
- Metadata for videos that take longer than ~6s to encode, without anyone touching the doc. The
common case. The upload's poll gives up at ~6s and the webhook is what fills
playbackOptionsin on its own. Without it the video stayspreparinguntil someone saves the doc, which refetches from Mux — so a missed event is recoverable, but only by hand. See Troubleshooting. - Mux → Payload delete sync. Deleting an asset in the Mux dashboard removes the Payload doc only
via the
video.asset.deletedevent. autoCreateOnWebhookbackfill. Importing assets you uploaded directly in Mux.
- The upload itself, and metadata for short videos (set synchronously by the 6s poll).
- Recovering a video stuck on
preparing. Saving the doc refetches the asset from Mux, so a webhook you never received doesn't strand the video. - Payload → Mux delete. Handled by the collection's
afterDeletehook, not the webhook. - Server-side ingest / seeding. The 6s limit doesn't apply; ingest waits for
readyand writes full metadata into the doc, so these play straight away whatever their length. - Playback of already-populated videos: the URLs compute on read from the stored playback id.
Server-side ingest
Besides the browser uploader, a mux-video can be created server-side from a local file or URL. This is handy for imports, migrations, and seeding. Pass a source; the beforeValidate hook uploads it to Mux, waits for the asset to be ready, fills in the metadata, and discards source.
import { ingestMuxVideo } from '@pro-laico/payload-mux'
await ingestMuxVideo(payload, { source: '/path/to/intro.mp4', title: 'Intro' })
// or a URL: ingestMuxVideo(payload, { source: 'https://example.com/intro.mp4', title: 'Intro' })
// playback policy comes from the plugin's `options.playbackPolicy`; pass { playbackPolicy: 'signed' } to override one video
// posterTimestamp: 12.5 picks the poster frame; defaults to the middle of the video
// collection: 'media' — only if you renamed the collection AND `payload` was built without the plugin; otherwise the marker's slug is usedLocal paths stream from disk, so ingesting a large file doesn't load it all into memory. Ingest is also what powers declarative seeding — see How it works.
Next
- Use a video — relate, play back, and sign playback URLs.
- How it works — the asset lifecycle, revalidation, and seeding.
- Troubleshooting — videos stuck on "preparing" and other fixes.