Video generation
Video is an asynchronous task API on the same key, under /v1/videos. The
shape follows OpenAI's video routes:
POST /v1/videoscreates a job and returns its id immediately.GET /v1/videos/{id}is polled until the job finishes.- Download the finished clip from
GET /v1/videos/{id}/content.
The gateway serves two video families:
| Group | Provider | Resolutions | Duration |
|---|---|---|---|
minimax-h3 | MiniMax | 768P, 2K | 4–15 s |
minimax-h3-max | MiniMax | 480P, 768P | 5–15 s |
seedance | BytePlus | 480p, 720p, 1080p | 4–30 s |
Try it
Generate a video
POST /v1/videosMiniMax H3 · billed per second
Create a job
curl -sS "https://llms.party/v1/videos" \
-H "Authorization: Bearer $LLMS_PARTY_KEY" \
-H "content-type: application/json" \
-d '{
"model": "minimax-h3",
"prompt": "A glass city at sunset, slow aerial push-in.",
"seconds": 4,
"resolution": "768P",
"ratio": "16:9"
}'const response = await fetch('https://llms.party/v1/videos', {
method: 'POST',
headers: {
authorization: `Bearer ${process.env.LLMS_PARTY_KEY}`,
'content-type': 'application/json',
},
body: JSON.stringify({
model: 'minimax-h3',
prompt: 'A glass city at sunset, slow aerial push-in.',
seconds: 4,
resolution: '768P',
ratio: '16:9',
}),
});
const job = await response.json();
console.log(job.id, job.status);import os
import requests
response = requests.post(
"https://llms.party/v1/videos",
headers={"Authorization": f"Bearer {os.environ['LLMS_PARTY_KEY']}"},
json={
"model": "minimax-h3",
"prompt": "A glass city at sunset, slow aerial push-in.",
"seconds": 4,
"resolution": "768P",
"ratio": "16:9",
},
timeout=60,
)
job = response.json()
print(job["id"], job["status"]){
"id": "video_...",
"object": "video",
"model": "minimax-h3",
"status": "queued",
"progress": 0,
"created_at": 1760000000
}| Field | Values |
|---|---|
model | A video group or one of its aliases. |
prompt | Text description of the shot. |
seconds | H3: 4–15. H3-Max: 5–15. Seedance: 4–30. |
resolution | Group-specific; see the table above (Seedance is lowercase). |
ratio | 16:9, 9:16, 1:1, 4:3, 3:4, 21:9. |
input_reference | Optional image URL for image-to-video. |
Poll
curl -sS "https://llms.party/v1/videos/$VIDEO_ID" \
-H "Authorization: Bearer $LLMS_PARTY_KEY"const job = await fetch(`https://llms.party/v1/videos/${videoId}`, {
headers: { authorization: `Bearer ${process.env.LLMS_PARTY_KEY}` },
}).then((response) => response.json());
console.log(job.status, job.progress);import os
import requests
job = requests.get(
f"https://llms.party/v1/videos/{video_id}",
headers={"Authorization": f"Bearer {os.environ['LLMS_PARTY_KEY']}"},
timeout=30,
).json()
print(job["status"], job.get("progress"))Statuses are normalized across providers: the gateway maps running to
in_progress and succeeded to completed, but older payloads may still say
succeeded. Terminal states are completed, failed and cancelled.
| Status | Meaning |
|---|---|
queued | Accepted, not started upstream yet. |
in_progress | Rendering; progress may be populated. |
completed | Ready to download. |
failed | error.message explains why. |
cancelled | Cancelled upstream. |
Polling every 2–5 s is plenty; renders take tens of seconds to a few minutes.
Download
curl -sS "https://llms.party/v1/videos/$VIDEO_ID/content" \
-H "Authorization: Bearer $LLMS_PARTY_KEY" \
-o clip.mp4import { writeFile } from 'node:fs/promises';
const response = await fetch(
`https://llms.party/v1/videos/${videoId}/content`,
{ headers: { authorization: `Bearer ${process.env.LLMS_PARTY_KEY}` } },
);
const clip = Buffer.from(await response.arrayBuffer());
await writeFile('clip.mp4', clip);import os
import requests
response = requests.get(
f"https://llms.party/v1/videos/{video_id}/content",
headers={"Authorization": f"Bearer {os.environ['LLMS_PARTY_KEY']}"},
timeout=300,
)
with open("clip.mp4", "wb") as clip:
clip.write(response.content)The response is video/mp4. The gateway streams the clip from the provider as
it downloads (Range requests are supported), so large 720p/1080p files are not
buffered.
MiniMax H3
MiniMax H3 and H3-Max render on the MiniMax platform and meter per second of output. H3 handles 768P and 2K; H3-Max handles 480P and 768P at a lower price.
| Group | 480P | 768P | 2K |
|---|---|---|---|
minimax-h3 | n/a | $0.08/s | $0.13/s |
minimax-h3-max | $0.05/s | $0.08/s | n/a |
BytePlus Seedance
seedance serves BytePlus ModelArk's Dreamina Seedance 2.5 on the same
/v1/videos API. It supports clips up to 30 seconds at 480p, 720p or 1080p,
from text or a single first-frame image.
curl -sS "https://llms.party/v1/videos" \
-H "Authorization: Bearer $LLMS_PARTY_KEY" \
-H "content-type: application/json" \
-d '{
"model": "seedance",
"prompt": "A glass city at sunset, slow aerial push-in.",
"seconds": 5,
"resolution": "720p",
"ratio": "16:9"
}'curl -sS "https://llms.party/v1/videos" \
-H "Authorization: Bearer $LLMS_PARTY_KEY" \
-H "content-type: application/json" \
-d '{
"model": "seedance",
"prompt": "The camera slowly pushes in as the lights come on.",
"input_reference": "https://example.com/frame.png",
"seconds": 5,
"resolution": "720p"
}'const body = {
model: 'seedance',
prompt: 'A glass city at sunset, slow aerial push-in.',
seconds: 5,
resolution: '720p',
ratio: '16:9',
// For image-to-video, add:
// input_reference: 'https://example.com/frame.png',
};
const response = await fetch('https://llms.party/v1/videos', {
method: 'POST',
headers: {
authorization: `Bearer ${process.env.LLMS_PARTY_KEY}`,
'content-type': 'application/json',
},
body: JSON.stringify(body),
});
const job = await response.json();
console.log(job.id, job.status);import os
import requests
body = {
"model": "seedance",
"prompt": "A glass city at sunset, slow aerial push-in.",
"seconds": 5,
"resolution": "720p",
"ratio": "16:9",
# For image-to-video, add:
# "input_reference": "https://example.com/frame.png",
}
response = requests.post(
"https://llms.party/v1/videos",
headers={"Authorization": f"Bearer {os.environ['LLMS_PARTY_KEY']}"},
json=body,
timeout=60,
)
job = response.json()
print(job["id"], job["status"])| Field | Seedance values |
|---|---|
seconds | 4–30, integer. |
resolution | 480p, 720p (default) or 1080p, lowercase. |
ratio | 16:9, 4:3, 1:1, 3:4, 9:16, 21:9; image input follows the image. |
input_reference | One image URL for the first frame. |
Reference video input and the editing and extension surfaces are not exposed through the gateway. One first-frame image is the supported input.
What Seedance costs
BytePlus bills Seedance by tokens, not per second. The price is per million tokens:
| Resolution | USD per 1M tokens | 5 s at 16:9 | 30 s at 16:9 |
|---|---|---|---|
| 480p | $10.70 | $0.514 | $3.08 |
| 720p | $10.70 | $1.156 | $6.94 |
| 1080p | $11.70 | $2.843 | $17.06 |
tokens = (input video seconds + output seconds) × width × height × fps / 1024For text-to-video the input-video term is zero. The polled task's
usage.total_tokens is the real token count. Only successful generations are
billed; failures, including moderation rejections, are free.
A 4 s 480p job took around two minutes in testing; longer clips take longer.
Rates: BytePlus ModelArk pricing. MiniMax rates are vendor list prices too; see MiniMax pricing.
Status and errors
A moderation rejection surfaces as failed, usually quickly. A 422 from
create means the request was rejected before a task existed (budget, model
access or validation), not a provider failure.