eroq

API reference · Platform

Films

Film projects — a script, a storyboard and an edit, on the video engines.

GETPOSTPATCHDELETE/v1/filmsFree

A film is a PROJECT, never media: a title, a shared look (engine, format, film type, era, tempo, camera…) and ordered scenes (prompt, camera move, duration, cast). Up to 50 per account — the studio's Cinema saves them here. Renders always land in /v1/creations; a film only points at them.

Cinema writes data as its v2 project ("v": 2): notes — the film's own notes (never sent to an engine); script — the scenes' order (one scene block per scene; text blocks from older drafts are folded into notes when the studio opens them); sequences — the Story's scenes (one place at one time, filmed in several shots), in film order, each with its heading (the slugline, prepended to every shot's prompt), cast (character ids whose sheets ride each of its shots), look (what it changes of the film's look) and notes; scenes — the SHOTS, each with its sequence (the id of the scene it belongs to; a scene's shots sit next to each other; a shot without one starts a scene, or joins the one before when it has no heading of its own), prompt (the action), dialogue ([{ speaker, manner, line }] — speaker is char:<id> or a free name), shot, seconds, cast, its notes (never sent), its link — how it is made from the scene before: absent = a new shot, { "type": "continue" } = the same shot going on (it opens on the last frame of the scene before), { "type": "angle" } = the same scene from another angle (that frame rides as a reference picture) — and the takes it rendered (options: library ids, pick = the one in the cut); edit — the timeline (clips with in/out and transitions, free audio clips, titles). The API stores data as sent (400 KB max); deleting a film never touches the renders it produced.

POST /v1/films/{id}/render shoots the whole storyboard in one call: every scene with a prompt is queued as an async video job (charged per scene, like POST /v1/videos/generations), the response maps each scene to its job id (poll them) or to the error that kept it from queueing. On a v2 project each scene's slugline and its dialogue lines ride its prompt (@Name (manner) says: "…"), and every speaking cast member joins its references (their voice too, on engines that take one). Scenes fail independently — a drained wallet stops the remaining queue cleanly, and every charged failure refunds itself. One call queues the first 24 shots with a prompt; a longer film (up to 100 shots) is rendered from the studio.

Media. GET /v1/films/{id} returns media: every take, clip and sound the project points at, as fresh signed URLs (the Store is private); POST /v1/films/media re-signs a list of keys (creation:<id>, upload:<id>) during a long session. The cut. The studio renders the edit to one MP4 in the browser and saves it with POST /v1/films/{id}/export (raw video/mp4 body, ≤ 95 MB, free — it counts against your storage); the saved cut is a library clip, and publishing it as the film's single segment puts the edited film on the community shelf.

The draft's look is applied to every scene: model, aspect, resolution, audio, seed and the director's rack (filmType, era, tempo, cameraType, lens, aperture, palette, lighting) — each scene adds its own prompt, shot, seconds and cast. Every engine takes the whole rack; a recurring cast keeps the same faces from scene to scene only on engines that read reference pictures (references in /v1/engines — Seedance, Kling, Veo 3.1, Hailuo 3, Wan). Start/end frames are per-clip controls of POST /v1/videos/generations, not part of a film. The studio's links between scenes are the same API used scene by scene: grab the previous clip's last frame, upload it (POST /v1/uploads) and send it as references[0] of the next POST /v1/videos/generations — as its first frame to continue the shot, or with reference_mode: "identity" for the same scene from another angle. POST /v1/films/{id}/render queues every scene at once, so it renders them as new shots.

A film can go public. POST /v1/films/{id}/cover (multipart file, image ≤ 5MB, free) sets its cover; POST /v1/films/{id}/publish puts the whole film on https://eroq.ai/community as one entry that plays the segments (your own hosted scene renders, in order) back to back — every URL must belong to a video in your library. DELETE /v1/films/{id}/publish makes it private again; likes and comments survive a re-publish. Deleting the draft deletes its community entry too (scene renders stay in the library).

Endpoints

Select a verb to load its request, playground and response.

GET/v1/filmsshown

List your film drafts.

POST/v1/films

Create a draft.

titlestring

Up to 80 characters.

dataobject

The recipe, stored verbatim: { look: {…}, scenes: [{ prompt, shot, seconds, cast }] }.

GET/v1/films/{id}

One film, full recipe.

PATCH/v1/films/{id}

Update title and/or data.

titlestring

New title, up to 80 characters.

dataobject

The whole recipe, replaced verbatim. Omit to keep the stored one.

DELETE/v1/films/{id}

Delete the draft — renders stay in the library.

POST/v1/films/media

Fresh signed URLs for media keys (creation:<id>, upload:<id>, up to 300) — unknown or foreign keys are left out.

keysarrayrequired

Media keys to sign.

POST/v1/films/{id}/export

Save the rendered cut (raw video/mp4 body, ?seconds=, ≤ 95 MB) to the library — free, counts against storage; replaces the film's previous unpublished cut.

POST/v1/films/{id}/render

Shoot the whole storyboard: one async video job per scene, charged per scene, jobs to poll in the response.

storeboolean

Persist every clip to the eroq Store (charged at the Store's rate). Default false.

folder_idstring

Library folder every scene's 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.

POST/v1/films/{id}/cover

Set the film's cover (multipart file, image ≤ 5MB). Free; shown on the community shelf and player. A new cover on an approved film sends it back to review (review in the response).

filefilerequired

Cover image, up to 5MB.

POST/v1/films/{id}/publish

Submit the film to the community: segments (your own hosted scene renders) play in order. It goes public once our team approves it — review starts at pending (readable on GET /v1/films/{id}); publishing again keeps the verdict unless the title, scenes or cover change.

segmentsarrayrequired

Ordered clip URLs (1–24). Each must be a hosted render from your own library — no foreign media.

titlestring

Public title, up to 120 characters. Defaults to the draft's title.

durationSecondsnumber

Total runtime shown as the duration badge.

DELETE/v1/films/{id}/publish

Take the film off the community shelf — engagement is kept for a re-publish.

curl https://eroq.ai/v1/films \
  -H "Authorization: Bearer $EROQ_API_KEY"
/v1/films
→ GET /v1/films
Press run — this replays a real exchange from the docs' own data. No key, no request, no charge.

Response

200 · application/json
{
  "films": [{
    "id": "7f2a…", "title": "Rooftop night",
    "scenes": 3, "updatedAt": "2026-09-11T14:02:11Z"
  }]
}