eroq

API reference · Media

Video generation

Start rendering a short clip — async, poll for the result.

POST/v1/videos/generationsper second by engine × resolution × sound — e.g. seedance-2-0-mini 9/s at 480p · veo-3-1 106/s with sound · eroq-motion-one 12/s

Video is slow by nature (one to five minutes, longer for 20–30 s takes), so this endpoint is asynchronous: the call charges, starts the render and answers 202 immediately with a job id. Poll GET /v1/videos/generations/{id} every few seconds until status is succeeded or failed.

The money guarantee is unchanged: credits are charged at submit, and a render that fails — or never completes within its engine's window — refunds itself automatically. You only ever pay for a delivered clip.

Pick THE engine with model: Seedance, Veo, Sora, Kling, Hailuo, Wan, Runway and Grok Imagine, plus Motion One, our own uncensored engine. The third-party engines are moderated upstream by their providers; a refused prompt or picture answers 400 content_blocked and bills nothing (the message says what was refused: the prompt, the starting picture, or the clip the engine rendered and then held back, refunded), and a picture the engine cannot read answers 400 invalid_image. Premium engines are plan-gated (403 plan_required before any charge) — GET /v1/engines lists what each engine takes and what your plan unlocks.

Engines are billed per second of clip, by resolution and — where it costs extra upstream — sound; a few also bill per picture sent. GET /v1/models quotes every rate; the response's usage.credits_spent is always the exact charge. Every knob is clamped to the engine BEFORE pricing: an unserved resolution renders (and bills) at the engine's default, a non-native aspect at its nearest native ratio.

Your cast and elements (elements) ride as numbered reference pictures on engines that read them (references in /v1/engines — up to six on Seedance): each character's look sheet holds its identity, @Name in the prompt binds to it. A start frame (references[0], on engines with image→video) takes over the clip instead — the cast then rides as text. With sound on, a cast member's voice rides along: Seedance 2.x and Hailuo 3 hear the voice sample itself (voice in /v1/engines), the others get a description of it. Write dialogue in quotes: @Mina says "we made it".

The finished clip is persisted to your library and served as a short-lived signed URL (or store: true for a permanent public URL, 2 credits / started 10MB on top). private: true writes nothing to your library: the clip is served through a temporary signed URL and its file is deleted 30 minutes after upload — the poll response carries expires_at and deletes_in_seconds.

Request body

promptstringrequired

The shot: subject, action, dialogue in quotes. @Name mentions bind to your cast and elements.

modelstring

Video engine id — see GET /v1/models (kind video) and GET /v1/engines. Default eroq-motion-one (every account). Retired ids (seedance-1-lite, kling-2-5-turbo, veo-3-fast, hailuo-02…) render on the model that replaced them. An engine not live on this deployment answers 503 model_unavailable.

secondsinteger

Clip length, 1–30. Your PLAN caps it (10s pay-as-you-go, 15/20/30s on Hobby/Creator/Studio+) and the engine's grid snaps it (e.g. Veo 4/6/8, Sora 4–20 by 4, Seedance 2.5 4–30) — billing always matches the clip that renders.

durationstring

Legacy shorthand (3s/5s/8s/10s) — ignored when seconds is present.

resolutionstring

480p, 720p, 768p, 1080p or 2K — each engine serves a subset (see /v1/engines resolutions); anything else renders at the engine's default. Priced per second per resolution.

fastboolean

HD quality (eroq-motion-one only): false runs the full 20-step base model with no turbo distillation instead of the default 8-step turbo — sharper and temporally steadier, slower, and billed at the engine's full rate (30 vs 12 credits/second). A 5-second HD clip is 150 credits. Ignored by every other engine.

aspectstring

16:9, 9:16, 1:1, 21:9, 4:3 or 3:4 — a native parameter on every engine that has it (/v1/engines aspects); a ratio the engine lacks renders at its nearest native one. retain (frame-driven engines, when you send a first frame) makes the canvas follow that frame's own ratio — the picture is never stretched.

audioboolean

Render the soundtrack with the picture — dialogue, ambience, effects (engines flagged in /v1/engines audio). Default on where supported; some engines bill sound per second.

referencesarray

Pictures. On engines with image→video (/v1/engines startFrame) the first one IS the first frame; elsewhere they join the reference pictures. URLs AND base64 data:image/... URIs are accepted — the studio sends a PASTED frame as a data URI; our own ComfyUI engine reads it inline, and on the upstream engines it is uploaded to our Store first.

reference_modestring

frame (default) or identity. With identity every picture in references rides as a reference picture — who or what stars, the engine builds the scene around it — never as the first frame (engines with /v1/engines references > 0). Seedance refuses pictures of real-looking people.

end_referencestring

END-frame picture — engines flagged in /v1/engines endFrame (Seedance, Veo, Kling, Hailuo, and our own Motion One) render the journey to it. Ignored elsewhere. URL or base64 data:image/....

elementsarray

Cast and ingredients, in order — characters as char:<id>, elements by id, previous image renders as creation:<id>, storage uploads as upload:<id>. Their look sheets/photos ride as numbered reference pictures up to the engine's budget (the rest ride as text); characters must carry an accepted look sheet or the call answers 422 sheet_required (see /v1/sheets).

seedinteger

Reproducibility seed — engines flagged in /v1/engines seed; ignored elsewhere.

negative_promptstring

What to steer away from — native on engines flagged in /v1/engines negative (Veo, Kling); ignored elsewhere.

shotstring

Camera move, 24 in the library: static, slow-pan, push-in, tracking, orbit, handheld, close-up, wide, pull-back, dolly-zoom, crane-up, crane-down, whip-pan, fpv, aerial-pullback, pov, snorricam, bullet-time, slider, roll, dutch-angle, overhead, crash-zoom, steadicam.

film_typestring

Film look: noir, documentary, music-video, commercial, arthouse, horror, romance.

erastring

Period look, 1920s → futuristic.

tempostring

Pacing: calm, dreamy, dynamic, tense, chaotic.

camera_typestring

Gear look: 35mm, imax, vhs, drone, gopro, cctv, smartphone.

lensstring

Glass: clean-sharp, anamorphic, vintage-anamorphic, soft-portrait, macro, fisheye.

aperturestring

Depth of field: f1-4 (wide open), f4, f11 (deep focus).

lightingstring

Lighting: silhouette, practicals, window-light, overhead-fall, contre-jour, soft-cross, neon-glow.

palettestring

Color: neon-noir, candy-pop, film-warm, nostalgic-blue, emerald, pastel-dawn, monochrome, sepia, industrial-fog, twilight, blood-gold, bleach-bypass.

storeboolean

Unlock a permanent public static URL for the clip. +2 credits per started 10MB. Default false.

folder_idstring

Library folder the clip lands in — one of yours (GET /v1/folders). Omitted = the Library root; an unknown id answers 404 folder_not_found before anything is billed.

flow_idstring

A flow to run on the clip once it lands — one of your flows (GET /v1/flows) that starts « After a render » of clips. Checked before anything is billed (403 plan_required below the plan flows take). Ignored by private renders. See Flows.

privateboolean

Do not retain on our side: the clip is NOT saved to your library. A video is served through a temporary signed URL and its file is deleted 30 minutes after upload (expires_at in the response); images are returned inline once. No creation row, nothing kept in our database. (Prompt retention upstream follows the per-model privacy value — see /v1/engines.) Default false.

advancedboolean

Advanced mode (eroq-motion-one only): the prompt rides RAW — no director rack folding, no directives, no enhancement. 400 advanced_requires_comfy on any other model.

curl https://eroq.ai/v1/videos/generations \
  -H "Authorization: Bearer $EROQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "seedance-2-0-mini",
  "prompt": "@Mina crosses the neon rooftop and says \"we made it\"",
  "seconds": 5,
  "resolution": "480p",
  "aspect": "9:16",
  "shot": "push-in",
  "lighting": "neon-glow",
  "elements": [
    "char:3f1c…"
  ]
}'
/v1/videos/generations
→ POST /v1/videos/generations
Press run — this replays a real exchange from the docs' own data. No key, no request, no charge.

Response

200 · application/json
{
  "id": "b7e6c2d4-…",
  "object": "video.generation",
  "status": "processing",
  "created": 1756118400,
  "model": "seedance-2-0-mini",
  "duration": "5s",
  "poll": "/v1/videos/generations/b7e6c2d4-…",
  "usage": { "credits_spent": 45, "credits_remaining": 887 }
}