OkayPic API Documentation

Generate AI videos and images programmatically via our REST API.

For AI coding assistants and tools: api.md (the whole reference in Markdown) · openapi.json (OpenAPI 3.1)

Authentication

All API requests require a Bearer token. Create an API key in your Developer Options page.

Authorization: Bearer okpk_your_api_key_here

Available Models

Prices for every model and option are on the Pricing page.

Video Models

Model IDLabelDurationRatios
minimax-h3MiniMax H3HOT1–15s16:9, 9:16
seedance-2.5Seedance 2.54–30s16:9, 9:16, 1:1
seedance-2.0Seedance 2.04–15s16:9, 9:16, 1:1
seedance-2.0-miniSeedance 2.0 Mini4–15s16:9, 9:16, 1:1
veo3.1Veo 3.1—16:9, 9:16

MiniMax H3 HOT — our cheapest video model

Model ID minimax-h3. Four modes via ref_mode. Ratios: 16:9, 9:16. Every mode is billed per second of output video at the resolution's rate.

ref_modeInputsNotes
omnimedia: up to 9 images + 3 audio clipsDefault. Refer to images in the prompt as <Picture 1>, audio as <Audio 1>.
first-lastfirst_frame (required) + last_frame (optional)media is not accepted. 480p / 768p only.
okay HOTfirst_frame / last_frame + media, all optionalOmni reference with locked frames — see below.
lip-syncmedia: exactly 1 image + 1 audioAudio-driven talking video — see below.
Effort (effort) — pay for a better render

Optional, defaults to "1x". Leave it out and nothing changes. Higher tiers put more work into each video: more detail, and the model follows a multi-shot prompt more closely — at 1x it sometimes skips a cut the prompt explicitly asks for.

effortPriceNotes
1xbase rateDefault — what every request got before this option existed.
1.5x+30% (768p: $0.013/s)Runs on our own GPUs only, so it can queue at busy times.
2x+60% (768p: $0.016/s)Runs on our own GPUs only, so it can queue at busy times.

Renders take noticeably longer — roughly 1.4x at 1.5x and 1.9x at 2x, more when demand is high. Works in every ref_mode at 480p and 768p. 1080p has no tiers — sending one returns 400.

Okay mode (ref_mode: "okay") — omni reference with locked frames HOT

H3-only. Pin the video's opening and/or closing frame with first_frame / last_frame while still using reference images (<Picture N>) and audio (voice timbre) from media.

  • Locked frames are not numbered: <Picture N> counts only the images in media.
  • No frames → same as omni (fastest). Frames only (no media) → same as first-last (a last frame alone uses the locked-frame path).
  • Frames plus media → the locked-frame path: 480p / 768p only, 5–15 s (≤ 6 s gives the best results). It is slower, and under heavy load a task may fail after waiting 30 minutes in the queue (failed tasks are refunded).
  • Same price as the other modes.
Lip Sync (ref_mode: "lip-sync")
  • media must be exactly one image and one audio clip. The image is the locked first frame; the audio is used as the video's soundtrack and drives the lips.
  • The video is as long as the audio (rounded up, max 15 s); pass duration only to cut it shorter. Billed per output second.
  • prompt is optional — use it to say who is speaking (when the image has several people) or how they move.
  • All three resolutions are supported.
resolutionDurationModes
480p1–15somni, first-last, okay, lip-sync
768p1–15somni, first-last, okay, lip-sync
1080p1–10somni, okay (without frames), lip-sync

Seedance Resolutions & Channels

Choose resolution and tier. third-party is the low-cost channel; official is the quality channel (a cheaper channel of the same model is tried first and a failed render is retried on the next one). Not every model has both tiers: asking for one it doesn't have returns 400. Billed seconds = duration + total reference-video seconds.

Model IDresolutiontierDurationMax refs (img / video / audio)
seedance-2.5720pofficial4–30s30 / 10 (30s) / 10 (30s)
seedance-2.5480pthird-party4–30s30 / 10 (30s) / 10 (30s)
seedance-2.5480pofficial4–30s30 / 10 (30s) / 10 (30s)
seedance-2.0720pthird-party4–15s9 / 3 (15s) / 3 (15s)
seedance-2.0-mini720pofficial4–15s9 / 3 (15s) / 3 (15s)

Veo 3.1 Variants

Variant IDLabelMax Images
veo3.1-fastFast2
veo3.1-componentsComponents3
veo3.1-proPro2

Image Models

Model IDLabelRatiosResolutions
doubao-seedream-5.0Seedream 5.01:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 21:91k, 2k, 4k
gpt-image-2.5GPT Image 2.51:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:31k, 2k, 4k
nano-banana-2.1Nano Banana 2.11:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3—
gpt-image-2GPT Image 21:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3—
gemini-3-pro-image-previewGemini 3 Pro Image1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 21:9—
gemini-3.1-flash-image-previewGemini 3.1 Flash Image1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 21:9—
gemini-2.5-flash-imageGemini 2.5 Flash Image1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3—

Endpoints

POST/api/video/generate

Submit a video generation task. For image models use POST /api/image/generate (see below). Send an Idempotency-Key header so retries never create a second task (see Idempotency below).

Request Body

ParameterTypeRequiredDescription
modelstringYesVideo model ID (see models table)
promptstringYes*Text description of the video to generate. *Optional for MiniMax H3 lip-sync
durationnumberNoVideo duration in seconds (model-dependent range)
ratiostringNoAspect ratio (e.g. "16:9", "9:16", "1:1")
variantstringNoFor Veo 3.1 only: variant ID (see variants table)
resolutionstringNoSeedance: "480p" / "720p" (default) / "1080p", where available. MiniMax H3: "480p" / "768p" (default) / "1080p"
ref_modestringNoMiniMax H3 only: "omni" (default), "first-last", "okay" or "lip-sync"
first_frame / last_framestringNoMiniMax H3 first-last and okay modes: the opening / closing frame (public https URL or base64 image data URI). Rejected in other modes.
optimize_promptbooleanNoMiniMax H3 only, default false. When true, an LLM rewrites your prompt into H3's official structured format (subject_definitions, shots, sound), using your reference images and audio. Prompts already in that format are used unchanged; if the rewrite fails the original prompt is used. No extra charge.
seedintegerNoMiniMax H3 only: 0–2147483647. Different seeds give different results. The same seed is not guaranteed to reproduce the same output — generations may run on different machines. Sending seed to any other model returns 400 (it is never silently ignored).
tierstringNoSeedance only: "third-party" (default when available) or "official"
mediaarrayNoReference media array. Each item: {type: "image"|"video"|"audio", url: "..."} — url is a public https URL or, for images and audio, a base64 data URI (see Reference media below). Constraints depend on model / resolution / tier.

Seedance Reference Media

  • Images, videos and audio can be mixed freely in media (omni reference). Limits per resolution / tier are in the Seedance table above.
  • Reference video seconds are added to the billed seconds. Audio references are not billed.
  • The legacy model id jimeng-video-seedance-2.0 still works and maps to seedance-2.0. Seedance 2.0 Fast is no longer available. ref_mode is ignored.

Other Models — Media Reference

  • Veo 3.1: 0–3 reference images (depends on variant, see table). Components is reference-to-video and needs 1–3 images; without any, the request runs as veo3.1-fast and is charged that price. No ref_mode needed.

Response

{
  "generationId": "3f6c…",
  "taskId": "3f6c…",          // same as generationId — use it to poll
  "status": "pending"
}
GET/api/video/tasks/{taskId}

Poll a task for its current status and results. /api/image/tasks/{taskId} works the same way for image tasks. Poll every 5–10 s; repeated polls within 5 s return the same cached status.

Response (completed)

{
  "status": "completed",
  "resultUrls": ["https://cdn.example.com/video.mp4"],
  "type": "video"
}

Response (processing)

{
  "status": "processing",
  "progress": 50,
  "type": "video"
}

Response (failed)

{
  "status": "failed",
  "errorMessage": "Content policy violation: …",
  "errorCode": "content_violation",
  "retryable": false,
  "type": "video"
}

Failed tasks are always refunded. Branch on errorCode / retryable, not on the message text:

errorCoderetryableMeaning
content_violationfalseThe provider flagged the prompt or reference media. Retrying the same input will fail again. Only set when the provider says so explicitly (currently MiniMax H3 and Gemini / GPT Image via our image channel).
generation_failedtrueThe provider failed for another reason (for Seedance, after trying every available channel). Retrying may succeed.
no_resulttrueThe provider reported success but returned no file, or it could not be saved.
timeouttrueNo result within 6 hours.
POST/api/image/generate

Submit an image generation task with an image model (see Image Models). Body fields: model, prompt, ratio, resolution (models that list resolutions), and images — an array of reference images (public https URLs or base64 data URIs). Some models answer immediately with "status": "completed" and resultUrls; otherwise poll GET /api/image/tasks/{taskId}.

curl -X POST https://api.okaypic.com/api/image/generate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "gemini-3.1-flash-image-preview", "prompt": "A red fox in the snow", "ratio": "1:1"}'

Response

{
  "generationId": "…",
  "taskId": "…",
  "status": "pending"            // or "completed" with "resultUrls": ["https://…"]
}

Idempotency (safe retries)

Both generate endpoints accept a client-chosen unique id per task, either as the Idempotency-Key header or as client_request_id in the JSON body (the header wins if both are set; 1–255 characters, scoped to your account).

  • Resubmitting with a key that already created a task does not create or charge a new one — you get the original taskId and its current status, with "idempotentReplay": true. Keep polling that task.
  • If the first request is still being processed, a concurrent retry gets 409 — wait a few seconds and retry with the same key.
  • If a request failed before a task was created (4xx/5xx from the generate call), the key is not used up — retry with the same key.
  • If the task itself failed (status: "failed", refunded), the same key keeps returning that failed task. To generate again, use a new key.
  • A replay returns the original task even if the retry body differs — use a new key for a different request.
curl -X POST https://api.okaypic.com/api/video/generate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: 541913da-s01_depot_daily_alert-clip1" \
  -H "Content-Type: application/json" \
  -d '{"model": "minimax-h3", "prompt": "…", "duration": 5}'

# Same request again (e.g. after a timeout on your side) →
# { "generationId": "3f6c…", "taskId": "3f6c…", "status": "processing", "idempotentReplay": true }

Reference media

Reference files go in media[].url (video endpoint) or images[] (image endpoint), in one of two forms:

  • Public URL — must be https:// and reachable from the internet (no login, no expiring link shorter than an hour). Required for videos.
  • Inline base64 — a data URI such as data:image/png;base64,iVBORw0…. Images (jpeg / png / webp) and audio only, ≤ 10 MB each, up to 12 per request, request body ≤ 40 MB. Inline files are kept only for generations that were actually created.
import base64, requests

with open("cat.jpg", "rb") as f:
    cat = "data:image/jpeg;base64," + base64.b64encode(f.read()).decode()

requests.post("https://api.okaypic.com/api/video/generate",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "model": "minimax-h3",
        "prompt": "<Picture 1> The cat jumps onto the sofa",
        "duration": 5,
        "resolution": "768p",
        "media": [{"type": "image", "url": cat}],
    })

Limits

  • Up to 20 tasks in progress per account at a time. Need more? Contact us on Telegram.
  • Per API key: 30 generate requests / minute and 600 requests / minute overall. Exceeding either returns 429 with a RateLimit header telling you when to retry.

Code Examples

# 1. Submit a video generation task — MiniMax H3 (our cheapest video model)
curl -X POST https://api.okaypic.com/api/video/generate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "minimax-h3",
    "prompt": "A cat playing piano in a jazz club",
    "duration": 5,
    "ratio": "16:9",
    "resolution": "768p",
    "effort": "1x"
  }'

# MiniMax H3 first/last frame
curl -X POST https://api.okaypic.com/api/video/generate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "minimax-h3",
    "prompt": "Smooth transition from dawn to dusk",
    "duration": 5,
    "resolution": "768p",
    "ref_mode": "first-last",
    "first_frame": "https://example.com/first.jpg",
    "last_frame": "https://example.com/last.jpg"
  }'

# MiniMax H3 Okay mode: omni reference with locked frames — starts on first_frame, ends on
# last_frame, while the <Picture N> references and the audio (voice timbre) are still used
curl -X POST https://api.okaypic.com/api/video/generate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "minimax-h3",
    "prompt": "<Picture 1> walks into the room and greets the camera",
    "duration": 6,
    "resolution": "768p",
    "ref_mode": "okay",
    "first_frame": "https://example.com/start.jpg",
    "last_frame": "https://example.com/end.jpg",
    "media": [
      {"type": "image", "url": "https://example.com/character.jpg"},
      {"type": "audio", "url": "https://example.com/voice.mp3"}
    ]
  }'

# MiniMax H3 lip sync: one image + one audio; the audio becomes the soundtrack
curl -X POST https://api.okaypic.com/api/video/generate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "minimax-h3",
    "ref_mode": "lip-sync",
    "resolution": "768p",
    "media": [
      {"type": "image", "url": "https://example.com/portrait.jpg"},
      {"type": "audio", "url": "https://example.com/speech.mp3"}
    ]
  }'

# Seedance: pick resolution + channel tier, with reference media (images / video / audio)
curl -X POST https://api.okaypic.com/api/video/generate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "seedance-2.5",
    "prompt": "Make this cat dance",
    "duration": 5,
    "ratio": "16:9",
    "resolution": "720p",
    "tier": "third-party",
    "media": [{"type": "image", "url": "https://example.com/cat.jpg"}]
  }'

# 2. Poll for task completion
curl https://api.okaypic.com/api/video/tasks/TASK_ID \
  -H "Authorization: Bearer YOUR_API_KEY"

# Response: { "status": "completed", "resultUrls": ["https://..."], "type": "video" }

Error Codes

StatusMeaning
400Bad request — invalid model, missing parameters, or wrong endpoint for the model type
401Unauthorized — invalid or missing API key
402Insufficient balance
409A request with the same Idempotency-Key is still being processed — retry shortly with the same key
429Too many tasks in progress (max 20) or rate limit exceeded
500Internal server error — backend generation failed