The POST response has no video, just an id
That’s expected.POST /v1/video/generations returns {"id": "t-..."}
immediately. The video isn’t ready yet.
- Poll
GET /v1/video/generations/{id}untilstatusis terminal, or - Pass a
callback_urlto receive the result by webhook. BytePlus, Kling and MiniMax models only. Any other model returns422for acallback_url; poll it instead.
HTTP 200 but the task failed
A task can fail after it was accepted. In that case the GET returns HTTP 200 withstatus: "failed" and an error object — the failure is in the
body, not the HTTP status.
status (succeeded / failed / expired / cancelled),
not just the HTTP code. Mesh’s own error.code values include
content_policy_violation, video_generation_failed, upstream_error,
provider_video_failed and task_abandoned. Any other code is the provider’s own.
The full table is in
A task that failed after it was accepted.
List endpoint shows a stale status
GET /v1/video/generations (the list) is served from Mesh’s database and does
not refresh from the provider. For a live status on an in-progress task,
call GET /v1/video/generations/{id} — that one forces an upstream sync.
Video / audio input rejected
Which inputs a model takes varies model by model, and the capability flags onGET /v1/models are the answer — supports_video_reference_video and
supports_video_reference_audio for these two. See
Finding out what a model accepts.
- A clip or an audio track is accepted by far fewer models than an image is. Check the flag before you rely on one.
- Some models will not take audio as the only media — send a reference image or a clip with it.
- Use
durationorframes, not both.
Request too large / Base64 failures
Total request body: 32 MiB (33,554,432 bytes) — a hard platform limit on every Mesh endpoint. Requests above it are rejected at the edge before they reach the API, so the response is a plain HTML413 Request Entity Too Large page with no
Mesh error envelope and no request ID. See
Rate Limits & Spend Caps.
Per-file caps are the model’s, and they are only reachable via public URLs, not
Base64 — see What you can send
for the widest ceilings. Base64 inflates a payload by ~33%, so a ~24 MB file on its
own already exceeds the 32 MiB body limit.
Do not Base64-encode large files. Use a public URL instead — it must be reachable
without authentication, since the model fetches it — and if you do inline small
files, the data URI must include the MIME prefix (e.g. data:video/mp4;base64,...).
422 on the create call
Two different causes, and the message tells them apart. Themodel ID isn’t a video-generation model. List the ones that are with
GET /v1/models?type=video, or check supports_video_generation on the model you had
in mind.
The model can’t take one of your content items — the message names it and says it
“would be dropped and the generation billed anyway”. supports_video_generation is
true here; the flag you need is the one for that input, e.g.
supports_video_last_frame. Check the six on GET /v1/models, or
GET /v1/models/{model_id}/providers to see whether any route takes it. Full detail:
Finding out what a model accepts.
Task shows ‘expired’
The task didn’t finish before its expiry window. On BytePlus models the default isexecution_expires_after = 172800 s (48 h); raise it on the create request
if you expect long jobs, or resubmit. Other providers ignore
execution_expires_after and apply their own window.
Task failed with task_abandoned
The provider never reported a terminal status. On providers without webhooks
(anything but BytePlus, Kling and MiniMax), Mesh closes a task that is still
unfinished an hour after creation and does not charge for it. Resubmit.
My webhook never fired
Callbacks are fire-and-forget with a 10-second timeout and are not retried.- Return a
2xxquickly (do heavy work after responding). A slow or failing endpoint means you miss the event. - Only BytePlus, Kling and MiniMax models take a
callback_url. Any other model is refused with422at create time. - Kling and MiniMax call back at most once, on a terminal state (
succeeded,failed,expired). If a poll (yours or Mesh’s own background check) settles the task first, no callback is sent. BytePlus forwards every status update, so ignore non-terminal deliveries such asrunning. - Treat polling
GET /v1/video/generations/{id}as the source of truth. Mesh deduplicates usage logging, so you’re never billed twice.
5xx from the video service
502— an upstream error while generating.503— video generation temporarily unavailable. Both are usually transient; retry with backoff.