curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "flux-3-video",
"prompt": "An orange cat jumps onto a sunlit wooden table, its tail brushes a glass that wobbles but does not fall. Cinematic, shallow depth of field.",
"duration": 5,
"resolution": "hd",
"aspect_ratio": "16:9"
}'
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "flux-3-video",
"prompt": "An orange cat jumps onto a sunlit wooden table, its tail brushes a glass that wobbles but does not fall. Cinematic, shallow depth of field.",
"duration": 5,
"resolution": "hd",
"aspect_ratio": "16:9",
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "flux-3-video",
prompt: "An orange cat jumps onto a sunlit wooden table, its tail brushes a glass that wobbles but does not fall. Cinematic, shallow depth of field.",
duration: 5,
resolution: "hd",
aspect_ratio: "16:9",
};
const headers = {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "flux-3-video",
"prompt": "An orange cat jumps onto a sunlit wooden table",
"duration": 5,
"resolution": "hd",
"aspect_ratio": "16:9",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
{
"error": {
"code": 422,
"message": "Parameter conflict or invalid value",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
FLUX 3 Video
FLUX 3 Video Generation
- Asynchronous processing mode, returns a task ID for subsequent queries
- Unified entry: text-to-video / image-to-video / video continuation / draft two-step
- Output H.264 + AAC with synced audio, duration 5~20 seconds
- Resolution hd / fhd, seven aspect ratios
POST
/
v1
/
videos
/
generations
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "flux-3-video",
"prompt": "An orange cat jumps onto a sunlit wooden table, its tail brushes a glass that wobbles but does not fall. Cinematic, shallow depth of field.",
"duration": 5,
"resolution": "hd",
"aspect_ratio": "16:9"
}'
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "flux-3-video",
"prompt": "An orange cat jumps onto a sunlit wooden table, its tail brushes a glass that wobbles but does not fall. Cinematic, shallow depth of field.",
"duration": 5,
"resolution": "hd",
"aspect_ratio": "16:9",
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "flux-3-video",
prompt: "An orange cat jumps onto a sunlit wooden table, its tail brushes a glass that wobbles but does not fall. Cinematic, shallow depth of field.",
duration: 5,
resolution: "hd",
aspect_ratio: "16:9",
};
const headers = {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "flux-3-video",
"prompt": "An orange cat jumps onto a sunlit wooden table",
"duration": 5,
"resolution": "hd",
"aspect_ratio": "16:9",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
{
"error": {
"code": 422,
"message": "Parameter conflict or invalid value",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
curl --request POST \
--url https://api.apimart.ai/v1/videos/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "flux-3-video",
"prompt": "An orange cat jumps onto a sunlit wooden table, its tail brushes a glass that wobbles but does not fall. Cinematic, shallow depth of field.",
"duration": 5,
"resolution": "hd",
"aspect_ratio": "16:9"
}'
import requests
url = "https://api.apimart.ai/v1/videos/generations"
payload = {
"model": "flux-3-video",
"prompt": "An orange cat jumps onto a sunlit wooden table, its tail brushes a glass that wobbles but does not fall. Cinematic, shallow depth of field.",
"duration": 5,
"resolution": "hd",
"aspect_ratio": "16:9",
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const url = "https://api.apimart.ai/v1/videos/generations";
const payload = {
model: "flux-3-video",
prompt: "An orange cat jumps onto a sunlit wooden table, its tail brushes a glass that wobbles but does not fall. Cinematic, shallow depth of field.",
duration: 5,
resolution: "hd",
aspect_ratio: "16:9",
};
const headers = {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(payload),
})
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error("Error:", error));
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.apimart.ai/v1/videos/generations"
payload := map[string]interface{}{
"model": "flux-3-video",
"prompt": "An orange cat jumps onto a sunlit wooden table",
"duration": 5,
"resolution": "hd",
"aspect_ratio": "16:9",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01J9HA7JPQ9A0Z6JZ3V8M9W6PZ"
}
]
}
{
"error": {
"code": 400,
"message": "Invalid request parameters",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 401,
"message": "Authentication failed, please check your API key",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "Insufficient account balance, please top up and try again",
"type": "payment_required"
}
}
{
"error": {
"code": 422,
"message": "Parameter conflict or invalid value",
"type": "invalid_request_error"
}
}
{
"error": {
"code": 429,
"message": "Too many requests, please try again later",
"type": "rate_limit_error"
}
}
Authorization
string
required
All endpoints require Bearer Token authenticationGet your API Key from the API Key Management Page:
Authorization: Bearer YOUR_API_KEY
Generation Modes
flux-3-video is a unified entry: mode is inferred from fields, or set explicitly with mode.
| Mode | Trigger | Notes |
|---|---|---|
| Text-to-video (t2v) | prompt only | Pure text |
| Image-to-video (i2v) | image_urls | Keyframes; see below |
| Video continuation (v2v) | video_url / video_urls | Higher unit price; if both image and video are set, continuation wins |
| Draft → final | draft:true or draft_from_task_id | Cheap preview, then full-price final |
mode values: t2v / i2v / v2v / draft_enhance, or official spellings text-to-video / image-continuation / video-continuation. Explicit mode has highest priority.
Image-to-video keyframe semantics
Order inimage_urls is semantic — do not sort or dedupe:
| Count | Meaning |
|---|---|
| 1 | Start frame |
| 2 | First start, second end frame |
| 3~10 | First start, last end, middle frames evenly spaced (set duration explicitly) |
Request Parameters
string
required
Fixed value:
flux-3-videoboolean
default:"false"
Whether to run content moderation before submitting the video task.
true: useomni-moderation-latestto review prompts and input imagesfalseor omitted: do not send a moderation request, adding no moderation cost or latency (default)
string
required
Prompt. Must not be sent when using
draft_from_task_id (rejected if present).integer
default:"5"
Duration in seconds, integer 5~20, default
5duration: "auto" is not supported (billing needs a fixed second count). Omit, "auto", or non-integers → treated as 5 seconds without error and without adaptive length.For video continuation, the delivered duration may be shorter than requested (e.g. request 5s, get 4s). The request is pre-charged for the requested seconds and the difference is refunded after completion; final amount is query
cost. Text/image-to-video do not show this gap.string
default:"hd"
Resolution
hd(default; also accepts720p)fhd(also accepts1080p)
hd ~1280×704 at 16:9; fhd ~1920×1088.Draft mode (
draft:true) only allows hd.string
default:"auto"
Aspect ratioOptions:
21:9, 2:1, 16:9, 4:3, 1:1, 3:4, 9:16, or auto (default; chosen automatically from the prompt and assets)string[]
Image-to-video keyframes, 1~10, public http(s) URL or base64
string
Input video for continuation (mp4, public URL or base64)
string[]
Same as
video_url; uses the first item (compat)boolean
default:"true"
Generate synced audio, default
true. false yields silent video (no discount)boolean
default:"false"
Draft mode: ~1/3 price low-quality preview; only with
resolution: hdstring
Draft → final: ID of your successful draft task
- Only
resolutionmay change; prompt, duration, images, video cannot - Charged at full final price; draft fee is not credited
- Mutually exclusive with
draft:true
integer
default:"2"
Moderation tolerance 0~4, default
2 (higher = more permissive)Do not confuse with FLUX.2 images (05) or Kontext (06).
string
Explicit mode (optional); see Generation Modes
Draft Mode
Two-step workflow when iterating is expensive:Step 1 draft:true → ~1/3 price low-quality preview
Step 2 draft_from_task_id → full-price final matching the draft look
Create draft
{
"model": "flux-3-video",
"prompt": "An orange cat jumps onto a sunlit wooden table",
"duration": 5,
"draft": true
}
Draft to final
{
"model": "flux-3-video",
"draft_from_task_id": "task_01K_DRAFT...",
"resolution": "fhd"
}
Request Examples
Text-to-video (portrait)
{
"model": "flux-3-video",
"prompt": "Rainy Tokyo street at night, neon in puddles, a person walks with an umbrella.",
"duration": 8,
"resolution": "fhd",
"aspect_ratio": "9:16"
}
Image-to-video (start + end frame)
{
"model": "flux-3-video",
"prompt": "Slow push-in as a flower opens from bud to bloom",
"image_urls": [
"https://example.com/bud.jpg",
"https://example.com/bloom.jpg"
],
"duration": 5
}
Video continuation
{
"model": "flux-3-video",
"prompt": "Camera keeps following as the lead turns toward a distant lighthouse",
"video_url": "https://example.com/clip.mp4",
"duration": 5
}
Silent video
{
"model": "flux-3-video",
"prompt": "...",
"audio": false
}
Constraints
| Limit | Value |
|---|---|
| Duration | Integer 5~20 (auto unsupported; 21 is rejected) |
| Keyframes | 1~10 |
| Resolution | hd / fhd only; draft only hd |
| Aspect ratio | Seven options or auto |
safety_tolerance | 0~4 |
Common submit errors (usually not charged)
| Case | Notes |
|---|---|
Missing prompt | Required except draft enhance |
Invalid resolution / aspect_ratio / duration | Out of range |
| Keyframes > 10 | Cap exceeded |
Explicit i2v without images / v2v without video | Mode/asset mismatch |
draft:true + fhd | Draft is hd only |
Invalid / non-draft / unfinished draft_from_task_id | Finalization preconditions |
| Changing prompt / duration on finalize | Only resolution allowed |
Both draft and draft_from_task_id | Mutually exclusive |
failed with full refund.
Capability Coverage
| Capability | Status |
|---|---|
| t2v / i2v / v2v | ✅ Auto or explicit mode |
| Draft / draft enhance | ✅ draft / draft_from_task_id |
| Synced audio | ✅ On by default; audio:false off (no discount) |
Timed keyframes [seconds, image] | ❌ Evenly spaced keyframe array only |
duration: "auto" | ❌ Not supported |
Response
integer
Status code; 200 on success
array
Query resultsVideo generation is async. Poll Get Task Status.Recommended interval 5~10 seconds; client timeout 15 minutes (20s fhd is slower). Measured ~60s for
t2v + hd + 5s.On success use result.videos[0].url; assets are mirrored to the platform CDN. cost is the final charge. Failures are fully refunded.