# OpenAI-compatible HTTP contract FastVideo exposes one model-agnostic REST engine for image and video models. Launch it from a typed serve config: ```bash fastvideo serve --config examples/serving/openai_fasth3.yaml ``` All generation routes share one serialized engine. FastVideo pipelines mutate per-request sampling state, and some adapters merge weights at load time, so a single loaded pipeline is never entered concurrently by image and video requests. HTTP handling and job polling remain asynchronous. ## Endpoints | Method | Path | Description | | --- | --- | --- | | `GET` | `/v1/models` | List the served model and optional startup adapter | | `GET` | `/v1/models/{model}` | Retrieve one served model card | | `POST` | `/v1/videos` | Submit an asynchronous video job | | `POST` | `/v1/videos/sync` | Generate and return an MP4 response directly | | `GET` | `/v1/videos` | List in-memory jobs with `after`, `limit`, and `order` | | `GET` | `/v1/videos/{id}` | Retrieve job status and metadata | | `GET` | `/v1/videos/{id}/content` | Download a completed MP4 | | `DELETE` | `/v1/videos/{id}` | Delete a job and its completed artifact | | `POST` | `/v1/images` | Generate an image | | `POST` | `/v1/images/edits` | Generate an image from image references | | `GET` | `/v1/images/{id}/content` | Download a generated image | | `GET` | `/health` | Liveness probe | `POST /v1/videos/generations` remains an alias for older FastVideo clients. ## Video requests The canonical shape follows vLLM-Omni and accepts SGLang's common flat extensions. Fields that FastVideo cannot represent for the loaded model fail at admission with HTTP 400 instead of creating a job that later fails. ```json { "model": "fasth3", "prompt": "A fox runs through fresh snow.", "seconds": "5", "size": "1344x768", "video_params": { "fps": 24, "num_frames": 124 }, "seed": 42, "num_inference_steps": 5, "guidance_scale": 1.0, "image_reference": [ {"image_url": "https://example.com/first-frame.png"} ], "extra_params": { "vsa_mode": "exempt" } } ``` Resolution precedence matches vLLM-Omni: 1. `size` 2. top-level `width` and `height` 3. `video_params.width` and `video_params.height` Top-level `fps` and `num_frames` similarly take precedence over the nested block. If `num_frames` is absent, `seconds * fps` is used. FastVideo also keeps the legacy `input_reference`, `reference_url`, `video_path`, and `video_url` spellings. Reference objects support URL or local-path strings through `image_url`, `video_url`, and `audio_url`. `file_id` references are schema-compatible but return HTTP 400 because FastVideo does not provide an OpenAI Files store. Image URLs, data URLs, local paths, and multipart `input_reference` uploads are materialized and decoded under the configured output directory during admission. Invalid media returns HTTP 400 before a job is created. ## Jobs and synchronous responses An asynchronous submission returns a `video` object in `queued` state. Its status advances through `in_progress` to `completed` or `failed`. Completed jobs expose `file_name`, the FastVideo compatibility extension `file_path`, timings, and peak-memory metadata when the pipeline reports them. `POST /v1/videos/sync` returns `video/mp4` bytes. It includes `X-Request-Id`, `X-Model`, `X-Inference-Time-S`, `X-Stage-Durations`, and `X-Peak-Memory-MB` headers. Its temporary MP4 is removed after the response is streamed. Asynchronous artifacts remain available until their job is deleted. Output paths are controlled by the server. Clients cannot choose filesystem destinations; every video is written beneath `server.output_dir` with a unique request id. FastVideo's synchronous CUDA execution cannot be interrupted after launch. Deleting an in-progress resource removes it from the API immediately; the engine remains serialized until the call exits and then removes any artifact. ## Model and LoRA selection `server.served_model_name` controls the public model id. If omitted, the checkpoint path is used. Requests that name another model fail with HTTP 400. LoRAs are configured under `generator.pipeline.components.{lora_path,lora_nickname,lora_strength}`. The startup adapter is the only model advertised by a LoRA server, and requests can select it by its model nickname or with a selector: ```json { "prompt": "A fox runs through fresh snow.", "model": "fasth3-dense-datafree", "lora": { "name": "fasth3-dense-datafree", "path": "/models/adapter_model.safetensors", "scale": 1.0 } } ``` The selector must match the adapter already loaded at startup. FastH3 adapter files can contain dense replacement tensors and VSA gates in addition to low-rank factors, so swapping them inside concurrent requests would corrupt shared pipeline state. A mismatch is rejected with HTTP 400. ## MiniMax-H3 and FastH3 FastH3 uses the same general routes and adapter. `task` is accepted for SGLang-compatible H3 clients: - `t2va` uses text only. - `fl2va` takes one or two image references. - `ref2va` takes ordered image, video, and audio references and requires a server started with `MiniMaxH3Ref2VAModularPipeline`. The released FastH3 pipeline generates one packed video/audio result per request, uses 24 fps, requires guidance scale 1, and accepts frame counts on its causal-VAE grid. The serving examples pin its five-point distilled sigma schedule (four DiT forwards). ## Defaults and errors Incoming explicit fields override operator-explicit `default_request` fields, which override model preset defaults. Pydantic defaults do not masquerade as client intent; the transport uses `model_fields_set`, while typed config parsing tracks the exact paths written by the operator. Errors use the OpenAI envelope: ```json { "error": { "message": "...", "type": "invalid_request_error", "param": null, "code": 400 } } ``` Parse, model-selection, startup-LoRA, and unsupported-parameter failures are HTTP 400; missing resources are HTTP 404; generation failures are stored on asynchronous jobs and returned as HTTP 500 when that job is retrieved. Unknown top-level fields are rejected. `extra_params` accepts only the explicit request-batch passthrough fields supported by the typed request adapter. `GET /health` also verifies that the generation engine is open and all local multiprocess workers are alive. It returns HTTP 503 when the worker pool is no longer usable.