Skip to content

Videos

Video generation is always asynchronous: submission returns 202 immediately, the job runs in the background (up to 30 minutes), and you collect the result by polling, webhook, or console.

Two submission routes — same engine, different shapes:

RouteShapeUse it when
POST /v1/videosOpenAI Video API (multipart, seconds+size)You use the OpenAI SDK (client.videos.create) or need image-to-video
POST /v1/videos/generationsMeshive JSON (resolution+duration+fps)Plain JSON integrations, text-to-video

Multipart form, OpenAI Video (Sora) style. Text-to-video or — by attaching input_reference — image-to-video, automatically matched against the model’s input modalities.

FieldTypeDefaultNotes
promptstringrequired
modelstringrequired
secondsfloatrequiredClip duration
sizestringrequiredWIDTHxHEIGHT, validated against the model’s supported resolutions
input_referencefileReference image → image-to-video
fpsint24
seed / negative_prompt / stepsMeshive extensions
webhook_urlstringMeshive extension
storage_credential_idintMeshive extension

Header: Idempotency-Key (semantics).

Response 202 — an OpenAI Video object:

{
"id": "req_4d5e6f7a8b9c0d1e",
"object": "video",
"status": "queued",
"model": "<model-id>",
"progress": 0,
"created_at": 1780000000,
"size": "720x1280",
"seconds": "5"
}
video = client.videos.create(
model="<model-id>",
prompt="A red fox running through fresh snow, cinematic",
seconds=5,
size="720x1280",
# input_reference=open("ref.png", "rb"), # ← image-to-video
)
print(video.id, video.status)

JSON body, text-to-video. (Image-to-video models must use POST /v1/videos.)

FieldTypeDefault
modelstringrequired
promptstringrequired
resolutionstring"720x1280"
durationfloat (seconds)5.0
fpsint24
seed / negative_prompt / steps
webhook_url / storage_credential_id

Response 202 — Meshive request shape (track via /v1/requests):

{ "id": "req_...", "object": "inference.request", "status": "queued", "modality": "video", "estimated_seconds": 30 }
  • Resolution/size must be in the model’s supported list — otherwise 422 resolution_not_supported with the valid options sorted in the message.
  • Models with a pinned native spec (most official video models are trained at one fixed frames/fps pair): duration/seconds must land within 0.5s of the native duration and fps must match exactly — otherwise 422 duration_mismatch / 422 fps_mismatch, with the supported values in the message.
  • Models without a pinned spec (typical for custom registrations): your duration × fps is honored, with the frame count snapped to the nearest value the architecture supports (4n+1, minimum 5). On the JSON route, resolutions are also snapped down to multiples of 32 — 718x1278 becomes 704x1248. Quality at off-native settings is the model’s behavior, not the platform’s.

Returns the Video object with current status:

statusMeaning
queuedWaiting for a worker
in_progressRunning — progress is a 0–99 estimate
completedDone — fetch /content
failedInspect the attached error: {code, message} — also covers requests that timed out (30 min) or expired
canceledCanceled while queued

302 redirect to a presigned download URL (valid ~1 hour; results in your own bucket are signed against it). Follow redirects in your HTTP client:

Terminal window
curl -L -o out.mp4 \
-H "Authorization: Bearer $MESHIVE_API_KEY" \
https://<your-deployment>.inference.meshive.ai/v1/videos/req_.../content

Not finished yet → 409 video_not_ready with the current status.

Cancels a queued video — 204. Consistent with the cancellation policy:

  • running409 video_not_cancellable (the GPU is already committed).
  • Already terminal (completed/failed/canceled) → 204 no-op (idempotent).