H3

Video Lab API

Using the local video generation API

This HTTP/JSON API submits MiniMax H3 text-to-video or first-frame image-to-video jobs, lets you poll their status, lists saved results, and serves video files. No API key is required on the local network.

Base URL: the same origin as this page, e.g. http://YOUR-H3-LAB-HOST:7862.

Machine-readable specification: OpenAPI 3.1 JSON. All timestamps in generation metadata are Unix seconds (UTC); generation duration is seconds.

Quick start: generate, poll, download

Submit a prompt; use the returned job_id to poll until the response says complete. Then GET the returned video path. Poll every 2–5 seconds rather than continuously.

BASE=http://YOUR-H3-LAB-HOST:7862
JOB=$(curl -fsS "$BASE/api/generate" \
  -H 'Content-Type: application/json' \
  -d '{"prompt":"A paper boat drifting through a sunlit stream","aspect":"16:9","quality":"preview","duration":5,"turbo":true,"steps":6,"seed":-1}' \
  | python3 -c 'import json,sys; print(json.load(sys.stdin)["job_id"])')

# Poll; continue while status is "running".
curl -fsS "$BASE/api/jobs/$JOB" | python3 -m json.tool

# When status is "complete", download the returned video path.
curl -f "$BASE$(curl -fsS "$BASE/api/jobs/$JOB" | python3 -c 'import json,sys; print(json.load(sys.stdin)["video"])')" \
  -o result.mp4

Endpoints

GET /api/config — capabilities and health

Returns the active model, backend health, available aspect ratios, qualities, durations, Turbo LoRA and optional additional LoRAs. Read this first instead of hard-coding model availability.

{
  "model": "minimax_h3_fl2va_pruned_int8_convrot.safetensors",
  "backend_ready": true,
  "turbo_available": true,
  "turbo_lora": "minimax_h3_turbo_v4_step600_ema_pruned_comfyui.safetensors",
  "loras": [{"id":"mystic-xxx-v4", "name":"Mystic XXX v4 (FL2VA)",
             "air":"urn:air:minimaxh3:lora:civitai:2856467@3266628+3150341",
             "default_strength":1.0}],
  "aspects": ["16:9","9:16","1:1","4:3","3:4","21:9"],
  "qualities": ["draft","preview","native"],
  "durations": [4,5,6,8,10,12,15]
}

backend_ready is a point-in-time check; retry if false.

POST /api/generate — enqueue a generation

Send a JSON object with Content-Type: application/json. Maximum request body is 30 MiB. Returns HTTP 202 with a job ID and normalized settings. The service supports one active ComfyUI generation at a time; jobs may wait in ComfyUI's queue.

FieldTypeAllowed values / behavior
promptstring, required1–12,000 characters (whitespace trimmed); include desired scene, motion and audio description.
aspectstring16:9, 9:16, 1:1, 4:3, 3:4, 21:9; default 16:9.
qualitystringdraft, preview, native; default preview.
durationnumber4–15 seconds; default 5. Values supported in the UI are advertised by config; the API accepts any number in range.
turbobooleanDefault false. Turbo sampler uses the installed Turbo LoRA at strength 1.0.
stepsintegerTurbo: 4–8 (default 6). Standard: 4–30 (default 20).
seedinteger or numeric string-1 or omitted chooses a random seed. Valid range: -1 through 263-1. Response returns the actual seed; reuse it for deterministic reruns.
start_imagestring or nullOptional data URI: data:image/png;base64,…, data:image/jpeg;base64,…, or data:image/webp;base64,…. Maximum decoded size 20 MiB. Crop/resize it to the selected aspect ratio before sending to avoid distortion.
lorastringOptional additional LoRA ID from /api/config, or empty/omitted. Current ID: mystic-xxx-v4.
lora_strengthnumber0–2, default 1.0; used when an additional LoRA is selected.

Example response:

{"job_id":"e8909c41-be4d-4405-816b-8b97fc430e59","settings":{"prompt":"A paper boat drifting through a sunlit stream","aspect":"16:9","quality":"preview","width":864,"height":480,"duration":5,"frames":124,"steps":6,"turbo":true,"seed":123456,"start_image":false,"lora":null,"lora_name":null,"lora_strength":null,"model":"minimax_h3_fl2va_pruned_int8_convrot.safetensors","created":1790093031.123}}

GET /api/jobs/{job_id} — poll job status

Poll with the job_id returned from generation. HTTP 200; state is in status:

{"status":"running"}
{"status":"complete","video":"/api/video?filename=…&subfolder=H3Lab"}
{"status":"error","error":"…"}

A completed result is returned only once ComfyUI has completed execution and saved its output. Make a GET to the returned video URL (relative to the same base URL). A non-existent/expired job is reported as status: error. Invalid job ID returns HTTP 400; unavailable ComfyUI returns 502.

GET /api/gallery — recent saved generations

Returns up to 24 newest videos and their metadata. Seeds are strings in gallery metadata to preserve full 64-bit precision.

{"items":[{"video":"/api/video?filename=…&subfolder=H3Lab","settings":{
  "prompt":"…","aspect":"9:16","quality":"preview","width":480,"height":864,
  "duration":5,"frames":124,"steps":6,"turbo":true,"seed":"123456",
  "start_image":false,"lora":"mystic-xxx-v4","lora_name":"Mystic XXX v4 (FL2VA)",
  "lora_strength":1.0,"model":"…","created":1790093031.123,"completed":1790093065.366,
  "generation_time_seconds":34.24
}}]}

Fields completed and generation_time_seconds may be estimated for older generations created before exact timing was recorded; such entries set generation_time_estimated: true.

GET /api/video?filename=…&subfolder=H3Lab — stream/download output

Use the relative video URL returned by a job or gallery item; do not construct a filesystem path. Supports standard HTTP byte ranges for browser playback and resume. Returns 200 for full file or 206 for a valid Range: bytes=start-end request. Missing files return 404.

POST /api/interrupt — interrupt current generation

Send Content-Type: application/json and body {}. Returns {"ok":true}. This signals ComfyUI's global interrupt endpoint and is not scoped to a job ID, so only call it to stop the active generation.

Errors and client guidance