Stories
Stories generate multi-scene illustrated narratives with consistent characters and style. Your AI assistant composes the storyboard and manages the workflow on your behalf.
Because generating multiple scenes takes time, stories use an async workflow.
How it works
Section titled “How it works”- Submit a storyboard: JSON with characters, scenes, and optionally locations and a style (see What goes in a storyboard).
- Receive HTTP 202 with a
job_idandpoll_url(the fullGET /v1/jobs/{job_id}URL). - Poll until status is
completedorfailed. - Download the scene images and the character and location reference images.
Stories need a model that can make multi-scene stories (supports_multiturn in GET /v1/models): today gemini and gemini-pro. Without model, Depicta uses your default model if it can, otherwise gemini. Other models return 422 model_not_capable.
What goes in a storyboard
Section titled “What goes in a storyboard”- characters (required, 1 to 10): a
name, anappearance, and optionally areference_urlto an image to match. Depicta makes a reference portrait of each character before the first scene. - scenes (required, 2 to 10): a
promptfor each. Say in the prompt who is in the scene, where it happens, and any change in how someone looks. - locations (optional, up to 10): a
nameplus adescriptionor areference_url. Before the first scene, Depicta makes one image of each described location (each one is charged like any other image) or fetches your reference image. Every location stays in view for all scenes. Scenes aren’t tied to a location, so name the place in the scene prompt. - style (up to 200 characters),
setting,prompt,aspect_ratioandimage_sizeapply to the whole story. Every scene uses the story’saspect_ratio.
Character and location names are short labels: up to 60 characters of letters (any script), digits, spaces and - _ ' ’ . , · ・ ׳ ་, with no space at the start or end.
Everything you write in a storyboard, names and style included, goes through the content check.
CLI usage
Section titled “CLI usage”depicta story run storyboard.jsonThe CLI polls automatically (every 3 seconds) and downloads all scene images when done. It waits up to 45 minutes (--timeout, in seconds), because a busy service can queue a story for up to 30 minutes before it starts.
If the wait runs out, or you press Ctrl+C, the CLI tells you the story is still running and will be charged when it completes, with its job ID: don’t resubmit it. Check on it with:
depicta story status <job_id>Waiting, limits and timeouts
Section titled “Waiting, limits and timeouts”- A timeout doesn’t stop the story. If the CLI or your own polling gives up, the story keeps running and is charged when it finishes. Check on it with
depicta story status <job_id>orGET /v1/jobs/{id}. Don’t submit it again: both stories would run, and both would be charged. - Busy service. A story can wait up to 30 minutes before its first scene (status
processing, 0 scenes done). If it can’t start in that time, it fails withservice_unavailableand nothing is charged. - Up to 3 stories in progress. Another one gets 429
rate_limit_exceededwith aRetry-Afterheader.
API usage
Section titled “API usage”Submit
Section titled “Submit”curl -X POST https://api.depicta.ai/v1/generate/story \ -H "Authorization: Bearer dpct_YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d @storyboard.jsonimport httpx, time
# Submitresp = httpx.post( "https://api.depicta.ai/v1/generate/story", headers={"Authorization": "Bearer dpct_YOUR_API_KEY"}, json=storyboard,)job = resp.json() # {"job_id": "...", "status": "pending", "poll_url": "https://api.depicta.ai/v1/jobs/..."}
# Pollwhile True: status = httpx.get( job["poll_url"], headers={"Authorization": "Bearer dpct_YOUR_API_KEY"}, ).json() if status["status"] in ("completed", "failed"): break time.sleep(3)Response (202 Accepted)
Section titled “Response (202 Accepted)”{ "job_id": "a1b2c3d4-e5f6-7890-abcd-ef0123456789", "status": "pending", "poll_url": "https://api.depicta.ai/v1/jobs/a1b2c3d4-e5f6-7890-abcd-ef0123456789"}Poll response (completed)
Section titled “Poll response (completed)”{ "job_id": "a1b2c3d4-...", "status": "completed", "scenes_completed": 4, "scenes_total": 4, "created_at": "2026-10-15T09:00:00Z", "started_at": "2026-10-15T09:00:01Z", "completed_at": "2026-10-15T09:04:30Z", "result": { "model": "google/gemini-3.1-flash-image", "title": "The Library of Aria", "scenes": [ { "scene": 1, "title": "Aria enters the library", "image_url": "https://media.depicta.ai/...", "expires_at": "2026-10-15T10:04:30Z", "image_hash": "sha256...", "formats": { "png": {"url": "https://media.depicta.ai/...", "format": "png"}, "jpeg": {"url": "https://media.depicta.ai/...", "format": "jpeg"}, "webp": {"url": "https://media.depicta.ai/...", "format": "webp"} } } ], "characters": [ {"name": "Aria", "reference_url": "https://media.depicta.ai/...", "expires_at": "2026-10-15T10:04:30Z"} ], "locations": [ {"name": "library", "reference_url": "https://media.depicta.ai/...", "expires_at": "2026-10-15T10:04:30Z"} ], "cost_eur": "0.420000", "balance_eur": "9.580000" }}cost_eur is the total for the whole story, in credits (EUR, excluding VAT; VAT is added when you buy credits). balance_eur is what you have left.
Poll response (failed)
Section titled “Poll response (failed)”{ "job_id": "a1b2c3d4-...", "status": "failed", "error": { "code": "service_unavailable", "message": "..." }}A failed job says why in error.code, and error.message says what happened and what to do. A story job can fail with:
error.code |
Meaning |
|---|---|
model_refused |
The model returned no image |
upstream_error |
The model rejected the request; retrying it unchanged fails |
upstream_unavailable |
The model was unavailable |
generation_failed, story_generation_failed |
Generation failed |
post_generation_failed |
An image was generated but could not be finished |
service_unavailable |
The story could not start in time |
timeout |
The story ran past the maximum time |
internal_error |
Unexpected server error |
abandoned |
The job never finished |
delivery_failed |
Generated and charged, but not delivered |