Videos
The Videos API generates a video clip from a text prompt, optionally conditioned on uploaded media — one or two images as first/last frames, or reference images, video clips, and audio clips. Rendering takes minutes rather than seconds, so it is an asynchronous job resource: you create a job, poll it until it reaches a terminal status, then download the output.
POST /v1/videosGET /v1/videosGET /v1/videos/modelsGET /v1/videos/acceptancePOST /v1/videos/acceptanceGET /v1/videos/{video_id}GET /v1/videos/{video_id}/contentGET /v1/videos/{video_id}/thumbnailOutput is MP4 with audio at 768p. Every request must specify aspect_ratio.
MiniMax H3 video generation runs on hardware in Japan.
Japanese scene descriptions are translated to English before generation. The translator is instructed to leave dialogue inside <d>…</d> and text depicted in the scene unchanged.
Agreement
Section titled “Agreement”A person must agree to the Video Service Terms in the console playground before they can start a job. After that, an API key used by that same person works. A teammate who has not agreed cannot start a job, even in the same organization.
Creating a job never records agreement. The only way to record it is POST /v1/videos/acceptance from a console login. An API key cannot agree.
GET /v1/videos/acceptance returns the current terms version and whether this person, in this organization, has agreed to it.
A missing agreement returns 403 with code agreement_required. Listing jobs, reading a job, and listing models stay open.
Create a job
Section titled “Create a job”curl https://api.aiand.com/v1/videos \ -H "Authorization: Bearer $AIAND_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "minimaxai/minimax-h3", "prompt": "A paper boat drifting down a rain-soaked gutter at dusk", "seconds": 8, "aspect_ratio": "16:9" }'| Field | Required | Notes |
|---|---|---|
model | yes | A model id from GET /v1/videos/models |
prompt | yes | Up to 7000 characters |
seconds | yes | Clip duration, 4–15 |
aspect_ratio | yes | One of Auto, 21:9, 16:9, 4:3, 1:1, 3:4, 9:16 |
image_reference | no | One or two images (purpose: "vision") with unique first_frame/last_frame roles (image-to-video) |
references | no | Reference media to condition on (reference-to-video): images, videos, audio. Cannot be combined with image_reference |
First and last frame (image-to-video)
Section titled “First and last frame (image-to-video)”Upload each image first and use the returned file_id. Each image must be a PNG, JPEG, or WebP file with purpose: "vision", at most 30 MiB — the engine rejects larger inputs even though the Files API accepts uploads up to 100 MiB.
curl https://api.aiand.com/v1/files \ -H "Authorization: Bearer $AIAND_API_KEY" \ -F "purpose=vision" \ -F "file=@first.jpg"Then submit one or two file references in customer-defined order:
curl https://api.aiand.com/v1/videos \ -H "Authorization: Bearer $AIAND_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "minimaxai/minimax-h3", "prompt": "A cinematic scene inspired by the references, natural motion", "seconds": 5, "aspect_ratio": "16:9", "image_reference": [ { "file_id": "file-first", "role": "first_frame" }, { "file_id": "file-last", "role": "last_frame" } ] }'The API validates that every file belongs to your organization and has purpose: "vision". It converts the stored R2 objects to short-lived signed URLs immediately before engine submission; public URLs are never required. Either role may be used alone, so a single first_frame does not require a last_frame. When both are supplied, their roles must be unique.
Reference images, video, and audio (reference-to-video)
Section titled “Reference images, video, and audio (reference-to-video)”To condition on reference media instead of frames, upload each file with the matching purpose — vision for images, video for clips, audio for sound — and pass the file_ids inside a references object:
curl https://api.aiand.com/v1/videos \ -H "Authorization: Bearer $AIAND_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "minimaxai/minimax-h3", "prompt": "A cinematic scene inspired by the references, natural motion", "seconds": 5, "aspect_ratio": "16:9", "references": { "images": [{ "file_id": "file-img1" }], "videos": [{ "file_id": "file-clip1" }], "audio": [{ "file_id": "file-aud1" }] } }'Counts, per-file sizes, and the total size are validated at request time. A reference video or audio clip longer than the video you request is trimmed: only its first part, as long as the requested seconds, is used. For an 8-second video, that is the first 8 seconds of each clip. For best results, use clips of 2–15 seconds.
| Reference | Purpose | Max count | Max size | Recommended length |
|---|---|---|---|---|
| image | vision | 8 | 30 MiB | — |
| video | video | 2 | 50 MiB | 2–15 s |
| audio | audio | 3 | 15 MiB | 2–15 s |
These rules apply:
- Frames and references cannot be mixed. A request uses
image_referenceorreferences— never both. They are separate request shapes. - Audio needs an anchor.
referencesmust include at least one image or video; audio alone is rejected. - At most 12 references in total. Within the per-type limits above,
referencesmay hold no more than 12 files altogether. - At most 256 MiB in total. Within the per-file limits above, all input files of one request may add up to no more than 256 MiB. A file used in two slots counts twice.
- Input files need an hour left. A frame or reference file that expires within the next hour is rejected. Upload it again.
- Each slot accepts certain formats. First and last frames and reference images: PNG, JPEG, or WebP. Reference videos: MP4, MOV, or WebM. Reference audio: WAV, MP3, FLAC, OGG, M4A, or audio in an MP4 or WebM file. Other formats, such as GIF or HEIC, are rejected.
- Input files must not be empty. A frame or reference file of 0 bytes is rejected.
- Images must be between 1:4 and 4:1. A frame or reference image whose long side is more than four times its short side is rejected.
- Images must have a standard, readable header. JPEGs must be 8-bit baseline or progressive; multi-picture JPEGs (such as some iPhone photos) and CMYK JPEGs are rejected. Ultra HDR photos are accepted. The image header must lie within the first 64 KiB; very large metadata can push it past that. Convert such files to a standard PNG or JPEG.
- Images must be still. Animated PNG and WebP files are rejected.
A request that breaks one of these rules is rejected with 400 invalid_value. Where possible, param names the input at fault.
The response is a job object with status: "moderating":
{ "id": "video_9f2c1b7e4a3d4e8fa1b0c9d8e7f6a5b4", "object": "video", "model": "minimaxai/minimax-h3", "prompt": "A paper boat drifting down a rain-soaked gutter at dusk", "seconds": 8, "status": "moderating", "error": null, "cost": "0.64000000", "currency": "usd", "created_at": 1755302400, "completed_at": null, "thumbnail": false}status is one of moderating, translating, queued, in_progress, completed, failed, or canceled. No job ends as canceled today. Treat any status you do not recognize as still running — new intermediate stages may be added. error is populated only when the job failed.
Input moderation
Section titled “Input moderation”Every job starts as moderating while its prompt and reference media are checked against our content policy. This normally takes a few seconds — up to about a minute when references are attached — and allowed jobs move to translating while the prompt is translated to English, then to queued, and render as usual. A request that violates the policy fails with error code moderation_blocked and is never billed:
{ "status": "failed", "error": { "code": "moderation_blocked", "message": "Your request was rejected by our content moderation system." }}If the moderation system itself is unavailable, the job fails closed with error code moderation_unavailable — nothing was judged and nothing is billed, so resubmit later. Likewise, if a Japanese prompt cannot be translated, the job fails closed with error code translation_unavailable — nothing is billed, so resubmit later.
Poll for completion
Section titled “Poll for completion”curl https://api.aiand.com/v1/videos/video_9f2c1b7e4a3d4e8fa1b0c9d8e7f6a5b4 \ -H "Authorization: Bearer $AIAND_API_KEY"A typical clip takes several minutes. Poll every 10–30 seconds until status is terminal — polling faster does not make a render finish sooner.
Download the output
Section titled “Download the output”Once status is completed, fetch the bytes. The response is the raw MP4, not JSON:
curl https://api.aiand.com/v1/videos/video_9f2c1b7e4a3d4e8fa1b0c9d8e7f6a5b4/content \ -H "Authorization: Bearer $AIAND_API_KEY" \ -o clip.mp4Requesting content for a job that is not completed returns 400.
Thumbnail
Section titled “Thumbnail”A completed job usually also has a JPEG still, 480 pixels wide, taken from near the start of the clip. thumbnail is true when the job has one to download; otherwise this returns 404, or 400 if the job isn’t completed:
curl https://api.aiand.com/v1/videos/video_9f2c1b7e4a3d4e8fa1b0c9d8e7f6a5b4/thumbnail \ -H "Authorization: Bearer $AIAND_API_KEY" \ -o clip.jpgThe thumbnail is free and is deleted together with the video.
List your jobs
Section titled “List your jobs”curl "https://api.aiand.com/v1/videos?limit=20" \ -H "Authorization: Bearer $AIAND_API_KEY"Returns newest first. limit defaults to 20 and caps at 100; pass after=<video_id> to page.
List video models
Section titled “List video models”Authentication is optional. With an API key, prices are shown in your organization’s billing currency; without one, prices are shown in USD. Requests without a key are rate-limited to 600 per minute per IP, one budget shared by every catalog endpoint callable without a key, including GET /v1/models.
curl https://api.aiand.com/v1/videos/modelsWith an API key:
curl https://api.aiand.com/v1/videos/models \ -H "Authorization: Bearer $AIAND_API_KEY"Each entry carries per-second pricing, one row per output resolution:
{ "object": "list", "data": [ { "id": "minimaxai/minimax-h3", "object": "video_model", "name": "MiniMaxAI/MiniMax-H3", "description": null, "pricing": [ { "resolution": "768p", "per_second": "0.080000", "currency": "usd" } ] } ]}Billing
Section titled “Billing”A render is priced as per_second × seconds and charged only when it completes. A job that fails or times out is never charged. A job cannot be canceled once submitted.
Because a render costs dollars and cannot be aborted part-way, its exact cost is fixed when the job is submitted: per_second × requested seconds. A job is refused unless your balance covers that quote plus the quoted costs of renders already in flight. This is stricter than the chat endpoints, which admit any request while the balance is above zero.
cost and currency contain that quote from the first response. The balance is deducted only after the render completes successfully.
Errors
Section titled “Errors”| Status | Code | Meaning |
|---|---|---|
400 | invalid_value | Bad body, out-of-range seconds, invalid or oversized references, or content requested before completion |
403 | agreement_required | This person has not agreed to the current Video Service Terms in the console playground |
402 | insufficient_credits | Balance does not cover the quoted cost of this render |
402 | monthly_budget_reached | Your organization’s remaining monthly budget does not cover this render plus renders already in flight |
404 | model_not_found | Unknown model, or one your plan is not entitled to |
429 | concurrency_limit_exceeded | You already have the maximum number of renders in progress for your plan |
429 | rate_limit_exceeded | More than 10 submit attempts in one minute from your organization; retry after Retry-After seconds |
409 | conflict | The job is still running, or is under review and cannot be deleted |
503 | provider_unavailable | No video engine is configured for this model |
An admitted job can also end failed, for example with one of these error codes. Failed jobs are never charged.
engine_unavailable: the video engine was unavailable. Resubmit later.engine_rejected: the engine could not process the job. Retrying with the same inputs will fail the same way; contact support if it persists.
Retention and deletion
Section titled “Retention and deletion”A finished job — the generated video and the job record, including its prompt — is deleted automatically 30 days after it finishes. Download anything you want to keep before then.
DELETE /v1/videos/{video_id} deletes one immediately:
curl -X DELETE https://api.aiand.com/v1/videos/video_abc123 \ -H "Authorization: Bearer $AIAND_API_KEY"{ "id": "video_abc123", "object": "video", "deleted": true }This is permanent and cannot be undone. A job that is still running has to finish first — poll it until its status is terminal, then delete.