<!-- /en/docs/video-api (en) -->

# Video API: 10 modules

REST contracts for Alibaba Video, HEYGEN AGENT, MARS, MOON, MiniMax, OMNI, SATURN, VECTOR, VENUS and X. Access and pricing depend on your account and the selected operation.

## Connection and lifecycle

Base URL: `https://apergrex.ru/franklab/api`. Tables show full paths. Send your FrankLab key in `X-API-Key`, or `Authorization: Bearer` for HEYGEN. Never put keys in URLs. Make labels and selectors select a request branch; they are not necessarily REST fields.

```bash
export FRANKLAB_BASE_URL="https://apergrex.ru/franklab/api"
# FRANKLAB_KEY is supplied securely by your environment.
```

Check availability and a model-specific estimate before creation. Generation POST may reserve Franks; F is an internal accounting unit. Save the returned ID and poll the specified route. HTTP 200, queued/processing and an ID do not establish completion. Success requires a terminal state and output URL. For 400 inspect fields, 401/403 access, 404 route/ID, 409 conflicts and 429 rate limits; also check application code/success and the error body. After a timeout, reconcile existing work before another paid POST. Check `cost_status` to see whether funds were reserved, charged or refunded.

Required marks fields mandatory for the selected REST branch; conditional requirements are stated alongside them. Path and query inputs are identified explicitly. Do not send every field from a union schema in one request.

## Modules

- [FrankLab Alibaba Video](#franklab-alibaba-video)
- [FrankLab HEYGEN AGENT](#franklab-heygen-agent)
- [FrankLab MARS](#franklab-mars)
- [FrankLab MOON](#franklab-moon)
- [FrankLab MiniMax](#franklab-minimax)
- [FrankLab OMNI](#franklab-omni)
- [FrankLab SATURN](#franklab-saturn)
- [FrankLab VECTOR](#franklab-vector)
- [FrankLab VENUS](#franklab-venus)
- [FrankLab X](#franklab-x)

## FrankLab Alibaba Video

For HappyHorse 1.1, use `720P` or `1080P`. If an existing task returns `lifecycle_conflict`, keep its ID and contact [support](/en/docs/contacts); do not create another task to retrieve the result.

HappyHorse 1.1 supports text and first-frame generation. REST normally omits `model`; Make's `happyhorse-1.1` label is not a REST model value. WAN uses `model:"wan3.0-video"`. Make `wan_t2v`, `wan_i2v`, `wan_r2v`, `wan_edit`, `wan_extend`, `wan_file`, `wan_link` map respectively to the seven REST operation values in the table. `hh10_edit` maps to `video_edit` with `model:"happyhorse-1.0-video-edit"`.

REST does not accept `wan3.0-video-prime`, even though Make lists it. For HappyHorse 1.1 use `720P`/`1080P`; HappyHorse 1.0 edit accepts 720P/1080P. Before submission, check access to the selected operation, especially WAN edit/extend/file/link and HappyHorse edit.

Image descriptor: `{storedFileId,url,mimeType,width,height,sizeBytes}` from owned stored media. WAN video descriptor: `{storedFileId,url,mimeType:"video/mp4",sizeBytes}`. HappyHorse edit video additionally requires measured `width,height,durationSeconds,fps` and permits MP4/MOV. Document descriptor requires owned ID/URL, supported document MIME and size, optionally `pageCount` (at most 50). Do not invent IDs or measured metadata. `/franklab/jobs/upload` returns `data.url`, `data.storedFileId`, `data.mimeType` and `data.sizeBytes`. For descriptors that also require measured geometry or duration, follow the [media input guide](/en/docs/integration).

WAN reference requests use `media:[{type:"reference_image",url:ownedURL}]` (up to 10); the current REST DTO additionally supports `referenceVideos` and `referenceAudios` with measured metadata, while this Make communication does not send those arrays. These are distinct from `referenceVideo`, the clip to edit. Automatic WAN duration `-1` reserves against a 30-second bound.

### Routes and operations

| Operation | HTTP | Path | Condition / purpose |
|---|---|---|---|
| `happyhorse_text_to_video` | POST | `/franklab/api/make/alibaba/videos` | Model/operation-specific assets are required as described below. Feature and operation gates must allow the request. Make wan3.0-video-prime is rejected by the current DTO. |
| `happyhorse_image_to_video` | POST | `/franklab/api/make/alibaba/videos` | Model/operation-specific assets are required as described below. Feature and operation gates must allow the request. Make wan3.0-video-prime is rejected by the current DTO. |
| `wan_t2v` | POST | `/franklab/api/make/alibaba/videos` | Model/operation-specific assets are required as described below. Feature and operation gates must allow the request. Make wan3.0-video-prime is rejected by the current DTO. |
| `wan_i2v` | POST | `/franklab/api/make/alibaba/videos` | Model/operation-specific assets are required as described below. Feature and operation gates must allow the request. Make wan3.0-video-prime is rejected by the current DTO. |
| `wan_r2v` | POST | `/franklab/api/make/alibaba/videos` | Model/operation-specific assets are required as described below. Feature and operation gates must allow the request. Make wan3.0-video-prime is rejected by the current DTO. |
| `wan_edit` | POST | `/franklab/api/make/alibaba/videos` | Model/operation-specific assets are required as described below. Feature and operation gates must allow the request. Make wan3.0-video-prime is rejected by the current DTO. |
| `wan_extend` | POST | `/franklab/api/make/alibaba/videos` | Model/operation-specific assets are required as described below. Feature and operation gates must allow the request. Make wan3.0-video-prime is rejected by the current DTO. |
| `wan_file` | POST | `/franklab/api/make/alibaba/videos` | Model/operation-specific assets are required as described below. Feature and operation gates must allow the request. Make wan3.0-video-prime is rejected by the current DTO. |
| `wan_link` | POST | `/franklab/api/make/alibaba/videos` | Model/operation-specific assets are required as described below. Feature and operation gates must allow the request. Make wan3.0-video-prime is rejected by the current DTO. |
| `hh10_edit` | POST | `/franklab/api/make/alibaba/videos` | Model/operation-specific assets are required as described below. Feature and operation gates must allow the request. Make wan3.0-video-prime is rejected by the current DTO. |
| `poll_status` | GET | `/franklab/api/make/alibaba/status/{taskId}` | Keep the returned ID; polling is a read of the existing task, never a new submission. |
| `estimate` | POST | `/franklab/api/make/alibaba/estimate` | Pricing-only, no reserve or provider egress. HTTP 200 can contain a non-200 application code. |
| `upload_source` | POST | `/franklab/api/franklab/jobs/upload` | Partner API key authentication. Response `{success:true,data:{url,storedFileId,mimeType,sizeBytes}}`; retained 7 days. See the [media input guide](/en/docs/integration) for measured metadata. |
| `connection_probe` | POST | `/franklab/api/make/alibaba/estimate` | Make connection check. For new tasks, use the operation-specific submit and status routes above. |

### REST parameters

`happyhorse_text_to_video`, `happyhorse_image_to_video`, `wan_t2v`, `wan_i2v`, `wan_r2v`, `wan_edit`, `wan_extend`, `wan_file`, `wan_link`, `hh10_edit`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `operation` | string | yes | text_to_video/image_to_video/reference_to_video/video_edit/video_extend/file_to_video/link_to_video. |
| `model` | string | conditional / no | Omit for HappyHorse 1.1; wan3.0-video or happyhorse-1.0-video-edit for other families. |
| `prompt` | string | yes | Nonempty, at most 5000 code points in service. |
| `resolution` | string | yes | Uppercase 480P/720P/1080P; use 720P/1080P for HappyHorse 1.1; HappyHorse 1.0 edit only 720P/1080P. |
| `durationSeconds` | integer | yes | HappyHorse 3–15; WAN 2–30 or -1 automatic (reserve for 30 seconds). |
| `ratio` | string | conditional / no | Required for HappyHorse text; adaptive only where model/operation permits. |
| `seed` | integer | conditional / no | Nonnegative seed. |
| `audio` | boolean | conditional / no | WAN audio. |
| `prompt_extend` | boolean | conditional / no | WAN prompt extension. |
| `watermark` | boolean | conditional / no | Watermark. |
| `firstFrame` | object | conditional / no | Owned image descriptor for image_to_video. |
| `lastFrame` | object | conditional / no | Optional WAN image_to_video final frame. |
| `media` | array | conditional / no | WAN reference images: [{type:reference_image,url:ownedURL}]. |
| `referenceVideo` | object | conditional / no | Owned video descriptor for WAN edit/extend. |
| `file` | object | conditional / no | Owned document descriptor for file_to_video. |
| `link` | string | conditional / no | HTTPS public web page for link_to_video; mutually exclusive with file. |
| `video` | object | conditional / no | HappyHorse edit video descriptor. |
| `referenceImages` | array | conditional / no | HappyHorse edit image descriptors, at most 5. |
| `audioSetting` | string | conditional / no | HappyHorse edit: auto/origin. |

`poll_status`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `taskId` | string | yes | Path: returned FrankLab task ID. |

`estimate`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `media` | string | yes | video. |
| `operation` | string | yes | Same operation as submit. |
| `model` | string | conditional / no | Same model as submit. |
| `resolution` | string | yes | Same resolution. |
| `durationSeconds` | integer | yes | Same duration. |

`upload_source`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `file` | binary | yes | Multipart file; 150 MiB maximum; supported image/video/audio MIME. |

### Response and completion

Envelope code/msg/data. Submit data.taskId and status=queued; poll queued/processing/completed/failed/error. Completed video is data.videoUrl; final_cost_franks, refunded_cost_franks and cost_status describe settlement.

### Minimal example

Replace OWNED_* placeholders with URLs of your own files. Check model access, the estimated cost and your available balance before submitting.

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/make/alibaba/videos" \
  -H "X-API-Key: $FRANKLAB_KEY" \
  -H "Content-Type: application/json" \
  --data '{"operation":"text_to_video","prompt":"A blue paper cube rotates on a white background.","resolution":"720P","durationSeconds":3,"ratio":"16:9"}'
```

Estimate: `POST /franklab/api/make/alibaba/estimate`. For Alibaba add media=video and send only estimate-schema fields.

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/make/alibaba/status/$TASK_ID" \
  -H "X-API-Key: $FRANKLAB_KEY"
```

## FrankLab HEYGEN AGENT

Authentication uses the partner credential/session guard; REST examples use your FrankLab bearer API key. `partner_heygen` requires a previously saved credential belonging to the same partner. Keep account mode and credential ID consistent across submit, session polling, resources, videos and RPCs. The normal example uses the FrankLab account and never sends a provider secret.

Make `avatarId`, `voiceId`, `styleId`, `brandKitId`, `callbackUrl`, `callbackId`, `incognitoMode` map to REST snake-case fields shown below. `filesJson` becomes an actual JSON array in `files`. List pagination is `limit` plus `token`; responses may include `hasMore` and `nextToken`. Save an avatar *look* ID, not its group ID.

For `generate_from_prompt`, POST `mode:"generate"`, GET the session until a video ID exists, then GET `/v1/heygen/videos/{videoId}` until a successful video URL exists. Failure/stopped/cancelled states are terminal; an empty URL is not success. A submit timeout or `submission_unknown` must be reconciled using existing session/task records before resubmitting. A session message can request further generation and is not a free metadata call. Stop is not a billing rollback. Provider-account and FrankLab-account billing paths differ; inspect the returned task/settlement evidence rather than assuming every session endpoint shares one tariff.

### Routes and operations

| Operation | HTTP | Path | Condition / purpose |
|---|---|---|---|
| `generate_from_prompt` | POST | `/franklab/api/v1/heygen/video-agents` | Make generate_from_prompt is a create → session poll → video poll composite, not /generate. |
| `create_session` | POST | `/franklab/api/v1/heygen/video-agents` | Make generate_from_prompt is a create → session poll → video poll composite, not /generate. |
| `list_sessions` | GET | `/franklab/api/v1/heygen/video-agents` |  |
| `list_styles` | GET | `/franklab/api/v1/heygen/video-agents/styles` |  |
| `get_session` | GET | `/franklab/api/v1/heygen/video-agents/{sessionId}` |  |
| `get_resource` | GET | `/franklab/api/v1/heygen/video-agents/{sessionId}/resources/{resourceId}` |  |
| `list_videos` | GET | `/franklab/api/v1/heygen/video-agents/{sessionId}/videos` |  |
| `get_video` | GET | `/franklab/api/v1/heygen/videos/{videoId}` |  |
| `send_message` | POST | `/franklab/api/v1/heygen/video-agents/{sessionId}/messages` |  |
| `stop_session` | POST | `/franklab/api/v1/heygen/video-agents/{sessionId}/stop` | Stopping is a mutation; it does not itself prove a refund. |
| `save_heygen_credential` | POST | `/franklab/api/v1/heygen/credentials` | Credential setup is a separate sensitive operation; never include provider keys in generation requests or public examples. |
| `getHeygenCredentials` | GET | `/franklab/api/v1/heygen/credentials` | Supporting Make RPC. The RPC function name is not part of the REST URL. |
| `getHeygenVideoAgentStyles` | GET | `/franklab/api/v1/heygen/video-agents/styles` | Supporting Make RPC. The RPC function name is not part of the REST URL. |
| `getHeygenAgentAvatarLooks` | GET | `/franklab/api/v1/heygen/avatars/looks` | Supporting Make RPC. The RPC function name is not part of the REST URL. |
| `getHeygenVoices` | GET | `/franklab/api/v1/heygen/voices` | Supporting Make RPC. The RPC function name is not part of the REST URL. |
| `getHeygenBrandKits` | GET | `/franklab/api/v1/heygen/brand/kits` | Supporting Make RPC. The RPC function name is not part of the REST URL. |
| `getHeygenVideoAgentSessions` | GET | `/franklab/api/v1/heygen/video-agents` | Supporting Make RPC. The RPC function name is not part of the REST URL. |
| `connection_probe` | GET | `/franklab/api/v1/heygen/credentials` | Make connection check. For new tasks, use the operation-specific submit and status routes above. |

### REST parameters

`generate_from_prompt`, `create_session`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `providerAccountMode` | string | conditional / no | franklab (default) or partner_heygen. |
| `providerCredentialId` | string | conditional / no | Required for partner_heygen; saved credential ID only. |
| `prompt` | string | yes | 1–10000 characters. |
| `mode` | string | conditional / no | generate or chat. |
| `avatar_id` | string | conditional / no | Avatar look ID. |
| `voice_id` | string | conditional / no | Voice ID. |
| `style_id` | string | conditional / no | Style ID. |
| `brand_kit_id` | string | conditional / no | Brand kit ID. |
| `orientation` | string | conditional / no | landscape/portrait. |
| `files` | array | conditional / no | At most 20 file entries; not a JSON-encoded string. |
| `callback_url` | string | conditional / no | Callback URL. |
| `callback_id` | string | conditional / no | Caller callback correlation. |
| `incognito_mode` | boolean | conditional / no | Private session flag. |

`list_sessions`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `providerAccountMode` | string | conditional / no | franklab (default) or partner_heygen. |
| `providerCredentialId` | string | conditional / no | Required for partner_heygen; saved credential ID only. |
| `limit` | integer | conditional / no | 1–100. |
| `token` | string | conditional / no | Pagination token. |

`list_styles`, `getHeygenVideoAgentStyles`, `getHeygenBrandKits`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `providerAccountMode` | string | conditional / no | franklab (default) or partner_heygen. |
| `providerCredentialId` | string | conditional / no | Required for partner_heygen; saved credential ID only. |

`get_session`, `list_videos`, `stop_session`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `providerAccountMode` | string | conditional / no | franklab (default) or partner_heygen. |
| `providerCredentialId` | string | conditional / no | Required for partner_heygen; saved credential ID only. |
| `sessionId` | string | yes | Path session ID. |

`get_resource`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `providerAccountMode` | string | conditional / no | franklab (default) or partner_heygen. |
| `providerCredentialId` | string | conditional / no | Required for partner_heygen; saved credential ID only. |
| `sessionId` | string | yes | Path session ID. |
| `resourceId` | string | yes | Path resource ID. |

`get_video`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `providerAccountMode` | string | conditional / no | franklab (default) or partner_heygen. |
| `providerCredentialId` | string | conditional / no | Required for partner_heygen; saved credential ID only. |
| `videoId` | string | yes | Path video ID. |

`send_message`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `providerAccountMode` | string | conditional / no | franklab (default) or partner_heygen. |
| `providerCredentialId` | string | conditional / no | Required for partner_heygen; saved credential ID only. |
| `sessionId` | string | yes | Path session ID. |
| `message` | string | yes | 1–10000 characters. |

`save_heygen_credential`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `label` | string | yes | Display label. |
| `apiKey` | secret | yes | Partner-owned HeyGen key; send only to credential storage. |

`getHeygenAgentAvatarLooks`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `providerAccountMode` | string | conditional / no | franklab (default) or partner_heygen. |
| `providerCredentialId` | string | conditional / no | Required for partner_heygen; saved credential ID only. |
| `ownership` | string | conditional / no | private for partner-owned credentials. |
| `limit` | integer | conditional / no | 50 in Make. |

`getHeygenVoices`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `providerAccountMode` | string | conditional / no | franklab (default) or partner_heygen. |
| `providerCredentialId` | string | conditional / no | Required for partner_heygen; saved credential ID only. |
| `type` | string | conditional / no | private for partner-owned credentials. |
| `limit` | integer | conditional / no | 100 in Make. |

`getHeygenVideoAgentSessions`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `providerAccountMode` | string | conditional / no | franklab (default) or partner_heygen. |
| `providerCredentialId` | string | conditional / no | Required for partner_heygen; saved credential ID only. |
| `limit` | integer | conditional / no | 50 in Make. |

### Response and completion

Envelope success=true,data,meta. Session and video IDs are separate. Session may return data.sessionId/videoId/status/providerStatus; poll video endpoint for data.video and videoUrl/downloadUrl. Read failureCode/failureMessage; session existence is not finished output.

### Minimal example

Replace OWNED_* placeholders with URLs of your own files. Check model access, the estimated cost and your available balance before submitting.

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/v1/heygen/video-agents" \
  -H "Authorization: Bearer $FRANKLAB_KEY" \
  -H "Content-Type: application/json" \
  --data '{"providerAccountMode":"franklab","prompt":"Create a short video of a blue paper cube rotating on a white background.","mode":"generate"}'
```

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/v1/heygen/video-agents/$SESSION_ID" \
  -H "Authorization: Bearer $FRANKLAB_KEY"
```

## FrankLab MARS

Text and image generation use `model_name:"mars-v1-5"`, duration 3–15 seconds, `mode:"std"|"pro"|"4k"`. The route chooses text/image intent; do not send Make `mode:"text2video"` as REST quality. Image generation requires `image` or `image_list`. Text generation rejects elements. Image generation allows at most three elements and rejects combining elements with voices. Multi-shot uses `multi_shot`, `shot_type` and `multi_prompt:[{index,prompt,duration}]`.

Effects require the exact `effect` code and scene. For example `effect_scene:"single_character",effect:"zoom_out",image:ownedURL`; dual-character inputs also need `image_tail`. The machine contract retains every effect selector value. Trajectory transfer is the same motion-control API documented under VECTOR, with Make's legacy aliases translated as noted. Poll the matching route family, retain all `task_result.videos`, and inspect `task_status_msg` if the task fails.

### Routes and operations

| Operation | HTTP | Path | Condition / purpose |
|---|---|---|---|
| `text2video` | POST | `/franklab/api/v1/videos/text2video` | Make quality_mode becomes REST mode; Make fixes model_name=mars-v1-5. |
| `poll_status` | GET | `/franklab/api/v1/videos/text2video/{taskId}` | Keep the returned ID; polling is a read of the existing task, never a new submission. |
| `image2video` | POST | `/franklab/api/v1/videos/image2video` | Make quality_mode becomes REST mode; Make fixes model_name=mars-v1-5. |
| `poll_status` | GET | `/franklab/api/v1/videos/image2video/{taskId}` | Keep the returned ID; polling is a read of the existing task, never a new submission. |
| `effects` | POST | `/franklab/api/v1/videos/effects` | Make effect_name becomes REST effect. Large scene-dependent effect catalogue is preserved in selectorValues in the contract map. |
| `poll_status` | GET | `/franklab/api/v1/videos/effects/{taskId}` | Keep the returned ID; polling is a read of the existing task, never a new submission. |
| `trajectory_transfer` | POST | `/franklab/api/v1/videos/motion-control` | Compatibility alias motion_control uses the same route. Make video maps to video_url; image is sent as image and image_url; anchor_source maps to character_orientation. |
| `poll_status` | GET | `/franklab/api/v1/videos/motion-control/{taskId}` | Keep the returned ID; polling is a read of the existing task, never a new submission. |
| `getAllKusoks` | GET | `/franklab/api/make/kusok/elements` | Supporting RPC; response data.result for elements, data for voices. |
| `getElementVoices` | GET | `/franklab/api/v1/elements/voices` | Supporting RPC; response data.result for elements, data for voices. |
| `upload_source` | POST | `/franklab/api/franklab/jobs/upload` | Partner API key authentication. Response `{success:true,data:{url,storedFileId,mimeType,sizeBytes}}`; retained 7 days. See the [media input guide](/en/docs/integration) for measured metadata. |
| `connection_probe` | GET | `/franklab/api/v1/videos/text2video` | Make connection check. For new tasks, use the operation-specific submit and status routes above. |

### REST parameters

`text2video`, `image2video`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `prompt` | string | conditional / no | Scene description. |
| `duration` | integer | yes | Clip seconds 3–15. |
| `model_name` | string | conditional / no | Public model alias. |
| `mode` | string | conditional / no | Quality mode. |
| `aspect_ratio` | string | conditional / no | Output ratio. |
| `callback_url` | string | conditional / no | Optional HTTPS callback. |
| `external_task_id` | string | conditional / no | Caller correlation ID, not a provider ID. |
| `negative_prompt` | string | conditional / no | At most 2500 characters. |
| `cfg_scale` | number | conditional / no | Guidance. |
| `sound` | boolean | conditional / no | Native audio (Make on/off is transformed). |
| `multi_shot` | boolean | conditional / no | Enable multiple shots. |
| `shot_type` | string | conditional / no | customize/intelligence. |
| `multi_prompt` | array | conditional / no | [{index,prompt,duration}] with positive integer shot duration. |
| `voice_list` | array | conditional / no | [{voice_id}]. |
| `image` | string | conditional / no | Start image URL for image2video. |
| `image_tail` | string | conditional / no | End image URL. |
| `image_list` | array | conditional / no | [{image_url,type?}]. |
| `element_list` | array | conditional / no | [{element_id}], at most 3 on mars-v1-5 image2video; excludes voice_list. |

`poll_status`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `taskId` | string | yes | Path: returned FrankLab task ID. |

`effects`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `effect_scene` | string | yes | single_character/dual_character. |
| `effect` | string | yes | Exact effect value from source selector. |
| `image` | string | yes | HTTPS input image. |
| `image_tail` | string | conditional / no | Second image required for dual-character Make scene. |
| `callback_url` | string | conditional / no | Callback. |
| `external_task_id` | string | conditional / no | Correlation. |

`trajectory_transfer`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `image` | string | yes | Anchor image URL or supported base64. |
| `image_file_data` | string | conditional / no | Alternative base64/native file data. |
| `image_file_name` | string | conditional / no | Filename for native data. |
| `video` | string | yes | Public reference video URL. |
| `character_orientation` | string | yes | image/video. |
| `mode` | string | conditional / no | std/pro. |
| `generation_profile` | string | conditional / no | auto/studio/cinema. |
| `keep_original_sound` | string | conditional / no | yes/no. |
| `prompt` | string | conditional / no | At most 2500 characters. |
| `duration` | string | yes | Required string seconds 3–30; image orientation at most 10. Must match reference clip. |
| `element_list` | array | conditional / no | [{element_id}]. |
| `callback_url` | string | conditional / no | Callback. |
| `external_task_id` | string | conditional / no | At most 100 characters. |

`getAllKusoks`, `getElementVoices`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `pageNum` | integer | conditional / no | 1-based. |
| `pageSize` | integer | conditional / no | Make asks for 500. |

`upload_source`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `file` | binary | yes | Multipart file; 150 MiB maximum; supported image/video/audio MIME. |

### Response and completion

Proxy envelope: code=0 (some routes accept 200), data.task_id. Poll data.task_status; successful task_result.videos[] contains url/id/duration. Read task_status_msg on failure. final_cost_franks is meaningful together with cost_status/cost_unit; reserved is not final settlement.

### Minimal example

Replace OWNED_* placeholders with URLs of your own files. Check model access, the estimated cost and your available balance before submitting.

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/v1/videos/text2video" \
  -H "X-API-Key: $FRANKLAB_KEY" \
  -H "Content-Type: application/json" \
  --data '{"model_name":"mars-v1-5","prompt":"A blue paper cube rotates on a white background.","duration":3,"mode":"std","aspect_ratio":"16:9"}'
```

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/v1/videos/text2video/$TASK_ID" \
  -H "X-API-Key: $FRANKLAB_KEY"
```

## FrankLab MOON

`moon_fast` Make resolution choices are 480p/720p; `moon_base` adds 1080p/4k; `moon_pro` offers 480p/720p/1080p and mp4/mov. `moon_mini` is exposed for reference generation. Model-specific validators remain authoritative: a union enum does not make every combination valid.

Image input uses `first_frame_image_url` and optionally `last_frame_image_url`. References are arrays of URL strings, not objects and not Make field labels. Standard limits are 9 images, 3 videos, 3 audios; `moon_pro` extends reference arrays to 30 images, 10 videos and 10 audios with additional aggregate budgets. The legacy `image_list` first-frame slots remain capped at 9. Edit/extend need the source video URL; give a prompt for a deliberate edit. Use direct public HTTPS URLs or URLs returned by upload.

Estimate with the identical payload, then submit with a stable `idempotency_key`. Keep the returned ID and poll `/make/moon/status/{taskId}`. Check application `code`, `phase`, `status`, output URL and settlement together. An estimated or reserved `final_cost_franks` is a reserve amount; `cost_status` distinguishes it from confirmed cost.

Duration is an integer 4–15 for non-pro models. moon_pro allows -1 (automatic) or 4–30; for moon_pro video_edit omit duration or use -1. For moon_pro edit/extend and first/last-frame inputs, omit ratio or use adaptive.

### Routes and operations

| Operation | HTTP | Path | Condition / purpose |
|---|---|---|---|
| `text_to_video` | POST | `/franklab/api/make/moon/videos` | Send operation=text_to_video. Make moon_model becomes moonModel; reference_image_url becomes first_frame_image_url. |
| `image_to_video` | POST | `/franklab/api/make/moon/videos` | Send operation=image_to_video. Make moon_model becomes moonModel; reference_image_url becomes first_frame_image_url. |
| `reference_to_video` | POST | `/franklab/api/make/moon/videos` | Send operation=reference_to_video. Make moon_model becomes moonModel; reference_image_url becomes first_frame_image_url. |
| `video_edit` | POST | `/franklab/api/make/moon/videos` | Send operation=video_edit. Make moon_model becomes moonModel; reference_image_url becomes first_frame_image_url. |
| `video_extend` | POST | `/franklab/api/make/moon/videos` | Send operation=video_extend. Make moon_model becomes moonModel; reference_image_url becomes first_frame_image_url. |
| `poll_status` | GET | `/franklab/api/make/moon/status/{taskId}` | Keep the returned ID; polling is a read of the existing task, never a new submission. |
| `estimate` | POST | `/franklab/api/make/moon/estimate` | Same payload as submission; pricing only, no provider dispatch. |
| `upload_source` | POST | `/franklab/api/franklab/jobs/upload` | Partner API key authentication. Response `{success:true,data:{url,storedFileId,mimeType,sizeBytes}}`; retained 7 days. See the [media input guide](/en/docs/integration) for measured metadata. |
| `connection_probe` | GET | `/franklab/api/v1/moon/videos/tasks/_connection_test_` | Make connection check. For new tasks, use the operation-specific submit and status routes above. |

### REST parameters

`text_to_video`, `image_to_video`, `reference_to_video`, `video_edit`, `video_extend`, `estimate`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `operation` | string | yes | text_to_video/image_to_video/reference_to_video/video_edit/video_extend. |
| `moonModel` | string | conditional / no | moon_fast/moon_base/moon_pro/moon_mini. |
| `prompt` | string | conditional / no | Required meaningful text or media per operation. |
| `duration` | integer | conditional / no | 4–15 seconds; moon_pro permits -1 automatic or 4–30. moon_pro video_edit requires -1 or omitted. |
| `ratio` | string | conditional / no | 21:9/16:9/4:3/1:1/3:4/9:16/adaptive. moon_pro edit/extend and frame modes require adaptive or omitted. |
| `resolution` | string | conditional / no | Model-dependent 480p/720p/1080p/4k. |
| `output_format` | string | conditional / no | moon_pro only mp4/mov. |
| `first_frame_image_url` | string | conditional / no | First frame URL. |
| `last_frame_image_url` | string | conditional / no | Optional last frame. |
| `reference_images` | array | conditional / no | URL strings. |
| `reference_videos` | array | conditional / no | URL strings. |
| `reference_video_url` | string | conditional / no | Single video URL alternative. |
| `reference_audios` | array | conditional / no | URL strings. |
| `reference_audio_url` | string | conditional / no | Single audio URL alternative. |
| `return_last_frame` | boolean | conditional / no | Return terminal frame. |
| `generate_audio` | boolean | conditional / no | Audio generation. |
| `watermark` | boolean | conditional / no | Watermark. |
| `priority` | integer | conditional / no | 0–9. |
| `safety_identifier` | string | conditional / no | Printable ASCII, at most 64 characters. |
| `execution_expires_after` | integer | conditional / no | 3600–259200 seconds. |
| `callback_url` | string | conditional / no | Callback URL. |
| `idempotency_key` | string | conditional / no | At most 200 characters. |
| `external_task_id` | string | conditional / no | Correlation, at most 200 characters. |

`poll_status`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `taskId` | string | yes | Path: returned FrankLab task ID. |

`upload_source`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `file` | binary | yes | Multipart file; 150 MiB maximum; supported image/video/audio MIME. |

### Response and completion

Envelope code/msg/data. Submit data.taskId/task_id, status=queued, phase and idempotency metadata; status queued/processing/completed/failed. Result data.videoUrl (or normalized video URL in result), last_frame_url if requested. A failed task can have HTTP 200 with code=500. Reserved final_cost_franks is not final settlement.

### Minimal example

Replace OWNED_* placeholders with URLs of your own files. Check model access, the estimated cost and your available balance before submitting.

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/make/moon/videos" \
  -H "X-API-Key: $FRANKLAB_KEY" \
  -H "Content-Type: application/json" \
  --data '{"operation":"text_to_video","moonModel":"moon_fast","prompt":"A blue paper cube rotates on a white background.","duration":4,"resolution":"480p","ratio":"16:9","generate_audio":false}'
```

Estimate: `POST /franklab/api/make/moon/estimate`. Use the same body.

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/make/moon/status/$TASK_ID" \
  -H "X-API-Key: $FRANKLAB_KEY"
```

## FrankLab MiniMax

All five scenarios are supported by the stored-file REST schema. Text requires a concrete ratio (21:9,16:9,4:3,1:1,3:4,9:16) and no reference fields. Frame scenarios require the corresponding owned ID(s), `ratio:"adaptive"`, and no reference arrays. Reference mode requires at least an image or video; audio alone is insufficient. Duplicate IDs across media arrays are rejected.

Upload URL JSON is `{source_type:"url",kind:"image",url:"https://your-public-host.example/synthetic.png"}`. For bytes use multipart `source_type=make_file`, `kind=image`, `media_file=@synthetic.png`; for a data URI use `data_url_file=@source.dataurl` with `source_type=data_url`. Upload transport caps one file at 64 MiB; per-media limits are smaller (image 30 MiB, video 50 MiB, audio 15 MiB). Reuse the returned `stored_file_id`.

The direct endpoint accepts one JSON *file*, not a JSON request body. Example file content for first frame: `{version:"minimax_h3_direct_v1",idempotency_key:"video-docs-frame-001",scenario:"first_frame_to_video",prompt:"A paper cube rotates.",resolution:"768P",duration:4,first_frame:{source_type:"stored_file",stored_file_id:"OWNED_FILE_ID"}}`. Make converts native file buffers to data URLs before building this file. Direct source kinds are stored_file/url/data_url; make_file is not a direct JSON source type.

Reuse the idempotency key for reconciliation of the same payload. A changed payload with the same key conflicts; `repeat_token` deliberately requests another generation and must not be added to evade a timeout. Respect 429 and retry timing; a failed polling request does not cancel provider work. No dedicated MiniMax estimate route was found in this controller.

### Routes and operations

| Operation | HTTP | Path | Condition / purpose |
|---|---|---|---|
| `upload_media` | POST | `/franklab/api/make/minimax/media` | Do not place a large data URI in a normal form field. Returns stored_file_id, media_kind, mime_type, size_bytes. |
| `issue_idempotency_key` | POST | `/franklab/api/make/minimax/idempotency-key` | Returns data.idempotency_key; a new key is not a retry policy. |
| `create_video:text_to_video` | POST | `/franklab/api/make/minimax/videos` | REST supports stored-file form. Make uses this JSON route for text; reference scenarios use videos/direct. |
| `create_video:first_frame_to_video` | POST | `/franklab/api/make/minimax/videos` | REST supports stored-file form. Make uses this JSON route for text; reference scenarios use videos/direct. |
| `create_video:last_frame_to_video` | POST | `/franklab/api/make/minimax/videos` | REST supports stored-file form. Make uses this JSON route for text; reference scenarios use videos/direct. |
| `create_video:first_last_frame_to_video` | POST | `/franklab/api/make/minimax/videos` | REST supports stored-file form. Make uses this JSON route for text; reference scenarios use videos/direct. |
| `create_video:reference_to_video` | POST | `/franklab/api/make/minimax/videos` | REST supports stored-file form. Make uses this JSON route for text; reference scenarios use videos/direct. |
| `create_video:direct` | POST | `/franklab/api/make/minimax/videos/direct` | Inside JSON: version=minimax_h3_direct_v1, idempotency_key, scenario (non-text), prompt, resolution, duration, optional repeat_token. first_frame/last_frame or reference_images/reference_videos/reference_audios carry source_type=stored_file / url / data_url and matching stored_file_id / url / data_url. Frame modes omit ratio; reference mode may supply ratio. |
| `get_video_task` | GET | `/franklab/api/make/minimax/videos/{taskId}` |  |
| `list_video_tasks` | GET | `/franklab/api/make/minimax/videos` | Also backs getMiniMaxVideoTasks RPC (page 1,size 100). |
| `cancel_or_delete_video_task:cancel` | POST | `/franklab/api/make/minimax/videos/{taskId}/action` | Mutation; confirm durable terminal state and settlement separately. |
| `cancel_or_delete_video_task:delete` | POST | `/franklab/api/make/minimax/videos/{taskId}/action` | Mutation; confirm durable terminal state and settlement separately. |
| `connection_probe` | GET | `/franklab/api/make/minimax/videos` | Make connection check. For new tasks, use the operation-specific submit and status routes above. |

### REST parameters

`upload_media`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `source_type` | string | yes | url/make_file/data_url. |
| `kind` | string | yes | image/video/audio. |
| `url` | string | conditional / no | HTTPS URL for URL upload. |
| `media_file` | binary | conditional / no | Multipart for make_file. |
| `data_url_file` | binary | conditional / no | Plain-text multipart file containing the data URI. |

`create_video:text_to_video`, `create_video:first_frame_to_video`, `create_video:last_frame_to_video`, `create_video:first_last_frame_to_video`, `create_video:reference_to_video`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `idempotency_key` | string | yes | Stable nonblank key, at most 200 characters. |
| `scenario` | string | yes | text_to_video/first_frame_to_video/last_frame_to_video/first_last_frame_to_video/reference_to_video. |
| `prompt` | string | yes | Nonblank, at most 7000 characters. |
| `resolution` | string | yes | 768P/2K. |
| `duration` | integer | yes | 4–15 seconds. |
| `ratio` | string | conditional / no | Text requires concrete ratio; frame modes require adaptive. |
| `first_frame_stored_file_id` | string | conditional / no | First owned image. |
| `last_frame_stored_file_id` | string | conditional / no | Last owned image. |
| `reference_image_stored_file_ids` | array | conditional / no | Up to 9 unique owned IDs. |
| `reference_video_stored_file_ids` | array | conditional / no | Up to 3 unique owned IDs. |
| `reference_audio_stored_file_ids` | array | conditional / no | Up to 3 unique owned IDs. |
| `repeat_token` | string | conditional / no | Deliberate repeat only, at most 64 characters. |

`create_video:direct`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `request_file` | binary | yes | One UTF-8 JSON multipart file, MIME application/json, at most 96 MiB. |

`get_video_task`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `taskId` | string | yes | Path local task ID. |
| `wait_seconds` | integer | conditional / no | Query integer 0–30; default 0. |

`list_video_tasks`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `page_num` | integer | conditional / no | 1-based. |
| `page_size` | integer | conditional / no | Query integer 1–100; default 20. |
| `status` | string | conditional / no | queued/running/succeeded/failed/cancelled. |
| `task_ids` | array | conditional / no | Optional IDs. |
| `model` | string | conditional / no | MiniMax-H3. |
| `task_type` | string | conditional / no | generation. |

`cancel_or_delete_video_task:cancel`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `taskId` | string | yes | Path local task ID. |
| `action` | string | yes | cancel. |

`cancel_or_delete_video_task:delete`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `taskId` | string | yes | Path local task ID. |
| `action` | string | yes | delete. |

### Response and completion

Envelope code=200,msg=OK,data. task_id; queued/running/succeeded/failed/cancelled; succeeded video/video_url and owned stored_file_id; reserved_cost_franks, final_cost_franks, cost_status, usage, error. Lists data.items/page_num/page_size/total.

### Minimal example

Replace OWNED_* placeholders with URLs of your own files. Check model access, the estimated cost and your available balance before submitting.

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/make/minimax/videos" \
  -H "X-API-Key: $FRANKLAB_KEY" \
  -H "Content-Type: application/json" \
  --data '{"idempotency_key":"video-docs-synthetic-001","scenario":"text_to_video","prompt":"A blue paper cube rotates on a white background.","resolution":"768P","duration":4,"ratio":"16:9"}'
```

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/make/minimax/videos/$TASK_ID" \
  -H "X-API-Key: $FRANKLAB_KEY"
```

## FrankLab OMNI

Google subscription mode uses an operator-managed queue. Confirm access and expected processing time before using it in a time-sensitive workflow.

The public OMNI module is separate from SATURN's legacy `/v1/videos/omni-video` alias. Use `/make/omni/videos`. Make `model=omni` selects `omni_version`; `model=veo` selects `veo_version`; the REST `model` is the resulting concrete value. `poll_status` is a GET operation, not a submit value.

For image-to-video supply one image source; for reference-to-video supply structured image references. A direct URL example is `{source:"url",image_url:"https://media.example.com/product-front.png",label:"cube"}`. Use the same partner's returned `interaction_id` for edit/extend; never a provider-secret identifier. Extend is limited to `omni_1_1`; `omni` 1.0 rejects it. Veo uses 4/6/8 seconds, its own resolution and negative prompt; those options do not confer support on the Omni engine. GET `/make/omni` lists capabilities and supported inputs.

`google_flow_sub` calls the separate Google subscription route with `execution_mode:"google_subscription"` and reference URL strings. Its polling envelope differs. Upload returns URL only; file-ID inputs require a real stored-file record. No dedicated estimate route exists in the Make OMNI controller.

### Routes and operations

| Operation | HTTP | Path | Condition / purpose |
|---|---|---|---|
| `text_to_video` | POST | `/franklab/api/make/omni/videos` | extend requires omni_1_1; Make omni_version/veo_version become model. |
| `image_to_video` | POST | `/franklab/api/make/omni/videos` | extend requires omni_1_1; Make omni_version/veo_version become model. |
| `reference_to_video` | POST | `/franklab/api/make/omni/videos` | extend requires omni_1_1; Make omni_version/veo_version become model. |
| `edit` | POST | `/franklab/api/make/omni/videos` | extend requires omni_1_1; Make omni_version/veo_version become model. |
| `extend` | POST | `/franklab/api/make/omni/videos` | extend requires omni_1_1; Make omni_version/veo_version become model. |
| `veo3` | POST | `/franklab/api/make/omni/videos` | Veo model route; live feature gate required. Make sends operation=text_to_video when omitted; image_file_id may supply the first frame. |
| `veo3_fast` | POST | `/franklab/api/make/omni/videos` | Veo model route; live feature gate required. Make sends operation=text_to_video when omitted; image_file_id may supply the first frame. |
| `poll_status` | GET | `/franklab/api/make/omni/status/{taskId}` | Keep the returned ID; polling is a read of the existing task, never a new submission. |
| `capabilities` | GET | `/franklab/api/make/omni` | Source capability response including supported operations/models and current Veo gate projection. |
| `google_flow_sub` | POST | `/franklab/api/v1/videos/google-sub` | Distinct subscription route; not model=google_flow_sub on make/omni/videos. |
| `poll_status` | GET | `/franklab/api/v1/videos/google-sub/{taskId}` | Keep the returned ID; polling is a read of the existing task, never a new submission. |
| `upload_source` | POST | `/franklab/api/franklab/jobs/upload` | Partner API key authentication. Response `{success:true,data:{url,storedFileId,mimeType,sizeBytes}}`; retained 7 days. See the [media input guide](/en/docs/integration) for measured metadata. |
| `connection_probe` | GET | `/franklab/api/make/omni` | Make connection check. For new tasks, use the operation-specific submit and status routes above. |

### REST parameters

`text_to_video`, `image_to_video`, `reference_to_video`, `edit`, `extend`, `veo3`, `veo3_fast`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `operation` | string | yes | text_to_video/image_to_video/reference_to_video/edit/extend. |
| `model` | string | conditional / no | omni/omni_1_1/veo3/veo3_fast. |
| `prompt` | string | yes | Nonempty, at most 2500 characters. |
| `aspect_ratio` | string | conditional / no | 16:9/9:16. |
| `image_url` | string | conditional / no | Image URL source. |
| `image_file_id` | string | conditional / no | Owned image ID. |
| `image_file_data` | string | conditional / no | Base64/native file source. |
| `image_file_name` | string | conditional / no | Filename for file data. |
| `image_base64` | string | conditional / no | Base64 source. |
| `reference_images` | array | conditional / no | [{source,image_url / image_file_id / image_base64 / image_file_data,image_file_name?,label?}]. |
| `previous_interaction_id` | string | conditional / no | Required existing partner-owned interaction for edit/extend. |
| `duration_seconds` | integer | conditional / no | Veo only 4/6/8. |
| `resolution` | string | conditional / no | Veo only 720p/1080p/4k. |
| `negative_prompt` | string | conditional / no | Veo only, at most 1000 characters. |

`poll_status`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `taskId` | string | yes | Path: returned FrankLab task ID. |

`google_flow_sub`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `execution_mode` | string | yes | google_subscription. |
| `prompt` | string | yes | Scene description. |
| `duration_seconds` | number | conditional / no | Make choices 4/6/8/10. |
| `aspect_ratio` | string | conditional / no | 16:9/9:16/1:1/4:3/3:4. |
| `reference_images` | array | conditional / no | URL strings. |

`upload_source`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `file` | binary | yes | Multipart file; 150 MiB maximum; supported image/video/audio MIME. |

### Response and completion

Make OMNI code/msg/data: taskId/task_id, status, videoUrl, interaction_id and billing fields. Poll completed/failed/processing; retain the interaction handle for edit/extend. google-sub uses proxy task_status/task_result.videos instead.

### Minimal example

Replace OWNED_* placeholders with URLs of your own files. Check model access, the estimated cost and your available balance before submitting.

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/make/omni/videos" \
  -H "X-API-Key: $FRANKLAB_KEY" \
  -H "Content-Type: application/json" \
  --data '{"model":"omni_1_1","operation":"text_to_video","prompt":"A blue paper cube rotates on a white background.","aspect_ratio":"16:9"}'
```

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/make/omni/status/$TASK_ID" \
  -H "X-API-Key: $FRANKLAB_KEY"
```

## FrankLab SATURN

Select `model_name:"saturn-v1"` or `"saturn-v1-5"`; do not send Make's `version` selector in REST. Standard SATURN supports text, images, reference video, elements, voices and multi-shot controls with model-specific constraints. A reference item is `{image_url:"https://media.example.com/product-front.png"}`; each item must carry exactly one source. Native/base64 image inputs are limited to 10 MiB each. Video reference entries use `video_url`, optionally `refer_type` and `keep_original_sound`. Voice list supports up to two IDs.

Turbo has two explicit routes and model `saturn-v1-5-turbo`; standard reference/multi-shot/audio/quality controls are not interchangeable. Image Turbo derives framing from the image; text Turbo can set aspect_ratio. Extension reuses an existing `video_id` or owner-scoped `source_task_id`; no new source ID can be invented. Multi-image generation has its own route and status route.

Save the status route for the selected variant together with its task ID. Legacy `/videos/omni-video` aliases belong to SATURN, not Gemini OMNI.

### Routes and operations

| Operation | HTTP | Path | Condition / purpose |
|---|---|---|---|
| `v1` | POST | `/franklab/api/v1/videos/saturn` | Make version selects model_name=saturn-v1. |
| `v1-5` | POST | `/franklab/api/v1/videos/saturn` | Make version selects model_name=saturn-v1-5. |
| `v1-5-turbo:text` | POST | `/franklab/api/v1/videos/saturn-turbo/text-to-video` | Do not send standard SATURN multi-shot/reference/sound/mode controls to Turbo. |
| `v1-5-turbo:image` | POST | `/franklab/api/v1/videos/saturn-turbo/image-to-video` | Do not send standard SATURN multi-shot/reference/sound/mode controls to Turbo. |
| `video_extend` | POST | `/franklab/api/v1/videos/video-extend` | Resolve a real source video; Make does not forward requested duration in extension. |
| `multi_image2video` | POST | `/franklab/api/v1/videos/multi-image2video` |  |
| `poll_status` | GET | `/franklab/api/v1/videos/saturn/{taskId}` | Keep the returned ID; polling is a read of the existing task, never a new submission. |
| `poll_status` | GET | `/franklab/api/v1/videos/saturn-turbo/{taskId}` | Keep the returned ID; polling is a read of the existing task, never a new submission. |
| `poll_status` | GET | `/franklab/api/v1/videos/video-extend/{taskId}` | Keep the returned ID; polling is a read of the existing task, never a new submission. |
| `poll_status` | GET | `/franklab/api/v1/videos/multi-image2video/{taskId}` | Keep the returned ID; polling is a read of the existing task, never a new submission. |
| `getAllKusoks` | GET | `/franklab/api/make/kusok/elements` | Supporting RPC; preserve returned IDs. |
| `getElementVoices` | GET | `/franklab/api/v1/elements/voices` | Supporting RPC; preserve returned IDs. |
| `upload_source` | POST | `/franklab/api/franklab/jobs/upload` | Partner API key authentication. Response `{success:true,data:{url,storedFileId,mimeType,sizeBytes}}`; retained 7 days. See the [media input guide](/en/docs/integration) for measured metadata. |
| `connection_probe` | GET | `/franklab/api/v1/videos/saturn` | Make connection check. For new tasks, use the operation-specific submit and status routes above. |

### REST parameters

`v1`, `v1-5`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `prompt` | string | conditional / no | Scene description. |
| `duration` | integer | yes | Clip seconds 3–15. |
| `model_name` | string | conditional / no | Public model alias. |
| `mode` | string | conditional / no | Quality mode. |
| `aspect_ratio` | string | conditional / no | Output ratio. |
| `callback_url` | string | conditional / no | Optional HTTPS callback. |
| `external_task_id` | string | conditional / no | Caller correlation ID, not a provider ID. |
| `sound` | string | conditional / no | on/off. |
| `image_list` | array | conditional / no | Exactly one image_url/image_base64/image_file_data source per item; optional image_file_name/type. |
| `video_list` | array | conditional / no | [{video_url,refer_type?,keep_original_sound?}]. |
| `element_list` | array | conditional / no | [{element_id}]. |
| `voice_list` | array | conditional / no | [{voice_id}], at most 2. |
| `multi_shot` | boolean | conditional / no | Multiple shots. |
| `shot_type` | string | conditional / no | customize/intelligence. |
| `multi_prompt` | array | conditional / no | [{index,prompt,duration}]. |

`v1-5-turbo:text`, `v1-5-turbo:image`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `model_name` | string | conditional / no | saturn-v1-5-turbo. |
| `prompt` | string | conditional / no | Required for text. |
| `image` | string | conditional / no | Required for image. |
| `duration` | integer | conditional / no | 3–15; default 5. |
| `resolution` | string | conditional / no | 720p/1080p. |
| `aspect_ratio` | string | conditional / no | Text only 16:9/9:16/1:1. |
| `callback_url` | string | conditional / no | Callback. |
| `external_task_id` | string | conditional / no | Correlation. |

`video_extend`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `video_id` | string | conditional / no | Existing output video ID. |
| `source_task_id` | string | conditional / no | Owner-scoped source task for resolving the video. |
| `prompt` | string | conditional / no | At most 2500 characters. |
| `negative_prompt` | string | conditional / no | At most 500. |
| `cfg_scale` | number | conditional / no | 0–1. |
| `callback_url` | string | conditional / no | Callback. |
| `external_task_id` | string | conditional / no | Correlation. |

`multi_image2video`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `image_list` | array | yes | [{image_url,type?}]. |
| `model_name` | string | conditional / no | Public model. |
| `prompt` | string | conditional / no | Up to 2500 characters. |
| `duration` | integer | conditional / no | 3–15. |
| `mode` | string | conditional / no | Quality. |
| `aspect_ratio` | string | conditional / no | Ratio. |
| `sound` | boolean | conditional / no | Native audio. |
| `element_list` | array | conditional / no | [{element_id}]. |
| `callback_url` | string | conditional / no | Callback. |
| `external_task_id` | string | conditional / no | Correlation. |

`poll_status`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `taskId` | string | yes | Path: returned FrankLab task ID. |

`getAllKusoks`, `getElementVoices`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `pageNum` | integer | conditional / no | 1-based. |
| `pageSize` | integer | conditional / no | Make requests 500. |

`upload_source`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `file` | binary | yes | Multipart file; 150 MiB maximum; supported image/video/audio MIME. |

### Response and completion

Proxy envelope: code=0 (some routes accept 200), data.task_id. Poll data.task_status; successful task_result.videos[] contains url/id/duration. Read task_status_msg on failure. final_cost_franks is meaningful together with cost_status/cost_unit; reserved is not final settlement.

### Minimal example

Replace OWNED_* placeholders with URLs of your own files. Check model access, the estimated cost and your available balance before submitting.

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/v1/videos/saturn" \
  -H "X-API-Key: $FRANKLAB_KEY" \
  -H "Content-Type: application/json" \
  --data '{"model_name":"saturn-v1","prompt":"A blue paper cube rotates on a white background.","duration":3,"mode":"std","aspect_ratio":"16:9"}'
```

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/v1/videos/saturn/$TASK_ID" \
  -H "X-API-Key: $FRANKLAB_KEY"
```

## FrankLab VECTOR

VECTOR transfers motion from a reference video to an anchor image. Provide an image and public video URL; Make describes a 3–30-second reference clip. `character_orientation:"image"|"video"` selects the orientation source, `keep_original_sound:"yes"|"no"` controls reference audio. Profiles are `auto`, `studio`, `cinema` (REST also accepts compatibility aliases vector-v1/vector-v1-5). Quality is std/pro.

For an image use URL, base64/data URI, or `image_file_data` plus `image_file_name` for native bytes. JPG/PNG/WebP, up to 10 MiB in the Make input contract. Optional elements are `{element_id}` objects. `list_tasks` is GET with query parameters and no creation body. The Make action/task selectors are not REST request fields. Generation requires a reference video and an anchor image; listing tasks only reads their metadata.

### Routes and operations

| Operation | HTTP | Path | Condition / purpose |
|---|---|---|---|
| `create` | POST | `/franklab/api/v1/videos/motion-control` | Make anchor_image→image, anchor_video→video, anchor_source→character_orientation, quality_mode→mode, preserve_reference_audio→keep_original_sound, reference_anchor_list→element_list. |
| `list_tasks` | GET | `/franklab/api/v1/videos/motion-control` | Partner-scoped list; data and pagination contain tasks. |
| `poll_status` | GET | `/franklab/api/v1/videos/motion-control/{taskId}` | Keep the returned ID; polling is a read of the existing task, never a new submission. |
| `upload_source` | POST | `/franklab/api/franklab/jobs/upload` | Partner API key authentication. Response `{success:true,data:{url,storedFileId,mimeType,sizeBytes}}`; retained 7 days. See the [media input guide](/en/docs/integration) for measured metadata. |
| `connection_probe` | GET | `/franklab/api/v1/videos/motion-control` | Make connection check. For new tasks, use the operation-specific submit and status routes above. |

### REST parameters

`create`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `image` | string | yes | Anchor image URL or supported base64. |
| `image_file_data` | string | conditional / no | Alternative base64/native file data. |
| `image_file_name` | string | conditional / no | Filename for native data. |
| `video` | string | yes | Public reference video URL. |
| `character_orientation` | string | yes | image/video. |
| `mode` | string | conditional / no | std/pro. |
| `generation_profile` | string | conditional / no | auto/studio/cinema. |
| `keep_original_sound` | string | conditional / no | yes/no. |
| `prompt` | string | conditional / no | At most 2500 characters. |
| `duration` | string | yes | Required string seconds 3–30; image orientation at most 10. Must match reference clip. |
| `element_list` | array | conditional / no | [{element_id}]. |
| `callback_url` | string | conditional / no | Callback. |
| `external_task_id` | string | conditional / no | At most 100 characters. |

`list_tasks`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `pageNum` | integer | conditional / no | Default 1. |
| `pageSize` | integer | conditional / no | Default 30. |

`poll_status`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `taskId` | string | yes | Path: returned FrankLab task ID. |

`upload_source`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `file` | binary | yes | Multipart file; 150 MiB maximum; supported image/video/audio MIME. |

### Response and completion

Proxy envelope: code=0 (some routes accept 200), data.task_id. Poll data.task_status; successful task_result.videos[] contains url/id/duration. Read task_status_msg on failure. final_cost_franks is meaningful together with cost_status/cost_unit; reserved is not final settlement.

### Minimal example

Replace OWNED_* placeholders with URLs of your own files. Check model access, the estimated cost and your available balance before submitting.

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/v1/videos/motion-control" \
  -H "X-API-Key: $FRANKLAB_KEY" \
  -H "Content-Type: application/json" \
  --data '{"generation_profile":"studio","mode":"std","image":"OWNED_SYNTHETIC_IMAGE_URL","video":"OWNED_SYNTHETIC_MOTION_VIDEO_URL","character_orientation":"image","keep_original_sound":"no","duration":"3"}'
```

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/v1/videos/motion-control/$TASK_ID" \
  -H "X-API-Key: $FRANKLAB_KEY"
```

## FrankLab VENUS

Provide an anchor image and either `sound_file` (URL/base64/native file) or an existing `audio_id`. Make documents MP3/WAV/M4A/AAC audio files up to 5 MiB and 2–60 seconds; audio IDs may represent 2–300 seconds and must be recent (30 days). Native fields are image_file_data/image_file_name and sound_file_data/sound_file_name. Do not send both audio alternatives.

Make creates `/v1/videos/avatar/image2video` then polls `/v1/tasks/{taskId}`. Success requires a video in `task_result.videos`. Read the returned billing fields and your transaction history; a missing amount does not mean the request was free.

### Routes and operations

| Operation | HTTP | Path | Condition / purpose |
|---|---|---|---|
| `create_avatar_video` | POST | `/franklab/api/v1/videos/avatar/image2video` | Supply one image source and one audio source; Make selectors image_source/audio_source/sound_input_source are not REST fields. |
| `poll_status` | GET | `/franklab/api/v1/tasks/{taskId}` | Keep the returned ID; polling is a read of the existing task, never a new submission. |
| `avatar_status` | GET | `/franklab/api/v1/videos/avatar/image2video/{taskId}` | Dedicated status alias; Make uses v1/tasks. |
| `upload_source` | POST | `/franklab/api/franklab/jobs/upload` | Partner API key authentication. Response `{success:true,data:{url,storedFileId,mimeType,sizeBytes}}`; retained 7 days. See the [media input guide](/en/docs/integration) for measured metadata. |
| `connection_probe` | GET | `/franklab/api/v1/videos/avatar/image2video` | Make connection check. For new tasks, use the operation-specific submit and status routes above. |

### REST parameters

`create_avatar_video`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `image` | string | yes | Image URL or base64. |
| `image_file_data` | string | conditional / no | Alternative native/base64 image bytes. |
| `image_file_name` | string | conditional / no | Filename. |
| `sound_file` | string | conditional / no | Audio URL/base64; alternative to audio_id. |
| `sound_file_data` | string | conditional / no | Alternative native/base64 audio. |
| `sound_file_name` | string | conditional / no | Filename. |
| `audio_id` | string | conditional / no | Existing compatible TTS audio ID; alternative to sound_file. |
| `prompt` | string | conditional / no | Optional performance prompt. |
| `mode` | string | yes | std/pro. |
| `callback_url` | string | conditional / no | Callback. |
| `external_task_id` | string | conditional / no | Correlation. |

`poll_status`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `taskId` | string | yes | Path: returned FrankLab task ID. |

`avatar_status`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `taskId` | string | yes | Returned task ID. |

`upload_source`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `file` | binary | yes | Multipart file; 150 MiB maximum; supported image/video/audio MIME. |

### Response and completion

Proxy envelope: code=0 (some routes accept 200), data.task_id. Poll data.task_status; successful task_result.videos[] contains url/id/duration. Read task_status_msg on failure. final_cost_franks is meaningful together with cost_status/cost_unit; reserved is not final settlement.

### Minimal example

Replace OWNED_* placeholders with URLs of your own files. Check model access, the estimated cost and your available balance before submitting.

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/v1/videos/avatar/image2video" \
  -H "X-API-Key: $FRANKLAB_KEY" \
  -H "Content-Type: application/json" \
  --data '{"image":"OWNED_SYNTHETIC_AVATAR_URL","sound_file":"OWNED_SYNTHETIC_AUDIO_URL","mode":"std"}'
```

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/v1/tasks/$TASK_ID" \
  -H "X-API-Key: $FRANKLAB_KEY"
```

## FrankLab X

Use `operation:"generation"` with text only, `image_url`, or `reference_images:[{url:ownedURL}]`. Image and reference arrays are mutually exclusive. Make's `source_mode` is a UI selector and is not sent to REST. For `edit` or `extension`, provide `video_url`, omit image/reference inputs; extension may omit prompt. Duration is 1–15 seconds for generation/edit and 2–10 for extension; Make exposes a smaller set of convenient choices.

Without an explicit recognized model, single-image generation selects the latest image-to-video model; text and references use the compatible model. 1080p is restricted to latest single-image generation. `execution_mode:"supergrok"` supports generation from text/images/references only, requires publicly accessible HTTPS image URLs and separate partner admission; no edit/extend/video input. Its supported output limits can differ from the direct xai_api route. Confirm access to the chosen execution mode before submission; do not switch modes automatically after a failure.

POST returns a FrankLab task ID; GET the same X route until terminal status and a usable URL. Keep cost_status with final_cost_franks. There is no dedicated estimate route in this controller; check your account’s pricing before creating a task.

### Routes and operations

| Operation | HTTP | Path | Condition / purpose |
|---|---|---|---|
| `generation:text_to_video` | POST | `/franklab/api/v1/videos/xai` | Make source_mode only chooses which REST inputs are sent. No silent execution-mode fallback. |
| `generation:image_to_video` | POST | `/franklab/api/v1/videos/xai` | Make source_mode only chooses which REST inputs are sent. No silent execution-mode fallback. |
| `generation:reference_to_video` | POST | `/franklab/api/v1/videos/xai` | Make source_mode only chooses which REST inputs are sent. No silent execution-mode fallback. |
| `edit` | POST | `/franklab/api/v1/videos/xai` | Make source_mode only chooses which REST inputs are sent. No silent execution-mode fallback. |
| `extension` | POST | `/franklab/api/v1/videos/xai` | Make source_mode only chooses which REST inputs are sent. No silent execution-mode fallback. |
| `poll_status` | GET | `/franklab/api/v1/videos/xai/{taskId}` | Keep the returned ID; polling is a read of the existing task, never a new submission. |
| `upload_source` | POST | `/franklab/api/franklab/jobs/upload` | Partner API key authentication. Response `{success:true,data:{url,storedFileId,mimeType,sizeBytes}}`; retained 7 days. See the [media input guide](/en/docs/integration) for measured metadata. |
| `connection_probe` | GET | `/franklab/api/v1/images/omni-image` | Make connection check. For new tasks, use the operation-specific submit and status routes above. |

### REST parameters

`generation:text_to_video`, `generation:image_to_video`, `generation:reference_to_video`, `edit`, `extension`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `operation` | string | yes | generation/edit/extension. |
| `execution_mode` | string | conditional / no | xai_api/supergrok. |
| `prompt` | string | conditional / no | Required except extension. |
| `image_url` | string | conditional / no | Single image input. |
| `reference_images` | array | conditional / no | [{url}] alternative to image_url. |
| `video_url` | string | conditional / no | Required for edit/extension. |
| `aspect_ratio` | string | conditional / no | Ratio for generation. |
| `resolution` | string | conditional / no | 480p/720p; 1080p only latest single-image generation. |
| `duration` | number | conditional / no | Generation/edit 1–15; extension 2–10; default 5. |

`poll_status`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `taskId` | string | yes | Path: returned FrankLab task ID. |

`upload_source`

| Field | Type | Required | Value / constraint |
|---|---|---|---|
| `file` | binary | yes | Multipart file; 150 MiB maximum; supported image/video/audio MIME. |

### Response and completion

Proxy envelope: code=0 (some routes accept 200), data.task_id. Poll data.task_status; successful task_result.videos[] contains url/id/duration. Read task_status_msg on failure. final_cost_franks is meaningful together with cost_status/cost_unit; reserved is not final settlement.

### Minimal example

Replace OWNED_* placeholders with URLs of your own files. Check model access, the estimated cost and your available balance before submitting.

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/v1/videos/xai" \
  -H "X-API-Key: $FRANKLAB_KEY" \
  -H "Content-Type: application/json" \
  --data '{"operation":"generation","execution_mode":"xai_api","prompt":"A blue paper cube rotates on a white background.","duration":1,"resolution":"480p","aspect_ratio":"16:9"}'
```

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/v1/videos/xai/$TASK_ID" \
  -H "X-API-Key: $FRANKLAB_KEY"
```

## Uploads and result retention

```bash
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/franklab/jobs/upload" \
  -H "Authorization: Bearer $FRANKLAB_KEY" \
  -F "file=@synthetic.png;type=image/png"
```

Upload returns `data.url`, `data.storedFileId`, `data.mimeType` and `data.sizeBytes`. Use `data.url` for URL fields. To obtain measured dimensions, duration or other descriptor metadata, send the returned `storedFileId` to the import route below. Save completed results before their retention expires.

### Import a reference and build its descriptor

For fields such as Alibaba `firstFrame`, import the image to obtain an owned file ID and measured metadata. Send exactly one source: a direct public HTTPS `url`, or the `storedFileId` from a previous upload under the same account. `kind` selects `image`, `video`, `audio` or `document`. Image import accepts PNG/JPEG/WebP up to 30 MiB; video MP4/MOV/WebM up to 100 MiB; audio up to 50 MiB; documents PDF/TXT/MD up to 20 MiB. Export office documents as PDF first. The target generation operation may impose smaller limits or fewer formats.

This example imports an image, selects its descriptor fields with `jq`, and submits a first-frame video request. Replace the example URL with your direct image link. The generation step uses your balance; import does not create a generation task.

```bash
set -e
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/franklab/jobs/import" \
  -H "Authorization: Bearer $FRANKLAB_KEY" \
  -H "Content-Type: application/json" \
  --data '{"url":"https://media.example.com/product-front.png","kind":"image"}' \
  -o imported-image.json

jq -e '.data | {storedFileId,url,mimeType,width,height,sizeBytes} | select(.storedFileId and .url and .width and .height)' imported-image.json > first-frame.json
jq -n --slurpfile firstFrame first-frame.json \
  '{operation:"image_to_video",prompt:"The product slowly rotates on a table.",resolution:"720P",durationSeconds:3,firstFrame:$firstFrame[0]}' > video-request.json
curl --fail-with-body -sS "$FRANKLAB_BASE_URL/make/alibaba/videos" \
  -H "X-API-Key: $FRANKLAB_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @video-request.json
```

For a previously uploaded image, replace the import body with `{"storedFileId":"ID_FROM_UPLOAD_RESPONSE","kind":"image"}`. Use the real `data.storedFileId`; do not send `url` in the same request.
