Examples
Picture and sound, made together
Every clip on this page was made with Sociaro Leda from one synthetic, AI-generated portrait of a fictional astronaut, from frames and sound we generated from it, or from text alone. Clips start muted; use the player to turn sound on.
Two references, two shots
ReferencesShot 1: she carries the shuttle model across a bright hangar and sets it on a plinth. Shot 2: medium close-up, she presents it and speaks to the camera.
Camera move copied from a video
ReferencesStudio product shot: the camera arcs around the shuttle model from left profile to right profile, following the camera move of the reference video.
New background, same speech
ReferencesReplace the grey studio backdrop with a bright hangar and a shuttle mock-up. Keep her motion and her line, "We launch at dawn."
Text only, to your own voice track
SoundtrackStatic medium close-up of a woman astronaut in an orange suit in a studio; she says "We launch at dawn.", then smiles and lowers her eyes to the helmet.
First, middle and last frame
KeyframesShe holds a thermos toward the camera, keeps it close at mid-clip, then sets it down beside the shuttle model and looks at it with a small smile.
Modes
What you can make
Every mode makes picture and sound together. Mix inputs the way the model was built to use them.
From references
A prompt plus up to 9 images, one video clip and 3 audio clips. Characters, objects, places, voices and music carry over into the clip. Audio needs at least one image or video next to it.
Leda Lite, Leda and Leda ProText only
A prompt and an aspect ratio.
Leda Lite, Leda and Leda ProFirst and last frame
A start image, an end image, or both. The clip begins or ends on your picture.
Leda Lite, Leda and Leda ProKeyframes
Images pinned to exact frames inside the clip, with or without a first and last frame (up to 9 images in total).
Leda Lite, Leda and Leda ProYour own soundtrack
An MP3 or WAV of 2 to 15 seconds. The video is made to your track: lips, nods and motion follow the sound, and the track plays back unchanged. A longer track is cut to the clip.
Leda Lite, Leda and Leda Pro
Quality
What Leda Lite, Leda and Leda Pro mean
We run Sociaro Leda on our own engine and judge every mode against the original model release, not against our own earlier output.
Leda Lite
2K · 5 sLeda Pro
2K · 5 sSame reference image, prompt and seed in both: "She holds her black helmet, slowly turns her head to her left, looks back at the camera and gives a small friendly nod. Steady medium shot."
Leda Lite
Sociaro Leda Lite is optimized by our team for speed and lower cost: a clip is ready in seconds, at a fraction of the price of the full model.
Leda
Sociaro Leda is optimized by our team as the middle option between Leda Lite and Leda Pro, priced between the two. It covers every mode, in 768P and 2K.
Leda Pro
Sociaro Leda Pro is optimized by our team with minimal loss of quality: in our tests it stays close to the original model. Use it when fidelity to your references matters. It covers every mode, in 768P and 2K.
2K upscale
Sociaro Leda generates at 768P and makes 2K directly from that original output, with an upscaler built into Sociaro Leda and optimized by our team. It doubles each side, for example 1344x768 to 2688x1536, adds sharpness and brings out fine details so they are easier to see. On Leda Lite, 480P can be upscaled the same way.
How we check
For each mode we render the same prompt, seed and references with the original model and compare by eye and by numbers. No original, no verdict.
| Clip | Leda Lite | Leda | Leda Pro |
|---|---|---|---|
| 5 s, 768P | 11 s | about 48 s | about 1 min 15 s |
| 5 s, 2K | 18 s | about 51 s | about 1 min 20 s |
| 10 s, 2K | 37 s | about 1 min 45 s | about 2 min 45 s |
| 15 s, 768P | 43 s | about 2 min 45 s | about 4 min 15 s |
| 15 s, 2K | 64 s | about 3 min | about 4 min 30 s |
Times run from creating the job to the finished clip through the API, with one reference image, outside busy times.
New modes (text only, frames, keyframes, your own soundtrack), 5 s, 768P: Leda Lite about 15 s, Leda about 29 s, Leda Pro about 47 s. Typical times; at busy times they can be longer.
With one reference, a 5 s Leda Pro clip takes about 1 min 20 s and a 15 s 2K clip about 4 min 30 s. Requests with many references near the limit take up to about 9 minutes. At busy times a job can also wait a few minutes in the queue.
Some hosted services are faster; we focus on staying close to the original model.
Formats
Sizes, ratios and lengths
| Resolution | 21:9 | 16:9 | 4:3 | 1:1 | 3:4 | 9:16 |
|---|---|---|---|---|---|---|
| 480P Leda Lite | 992x416 | 864x480 | 640x480 | 480x480 | 480x640 | 480x864 |
| 480P, upscaled x2 Leda Lite | 1984x832 | 1728x960 | 1280x960 | 960x960 | 960x1280 | 960x1728 |
| 768P (default) | 1536x672 | 1344x768 | 1024x768 | 768x768 | 768x1024 | 768x1344 |
| 2K (768P upscaled x2) | 3072x1344 | 2688x1536 | 2048x1536 | 1536x1536 | 1536x2048 | 1536x2688 |
- Aspect ratio: pick one of the six, or
adaptiveto follow your first image or video. Text-only clips, and a soundtrack without an image, need a fixed ratio. - Length: any whole number of seconds from 4 to 15. A 4-second request returns the shortest clip the model makes, about 5.2 seconds.
- Frame rate: 24 fps.
- Sound: generated with the picture in every mode, or your own track in soundtrack mode.
- File: MP4 (H.264) with audio.
- 480P: Leda Lite only, for drafts. The model was trained at 768P: 480P is quicker and cheaper for tests; use 768P or 2K for final work.
9:16
21:9
On a desert launch field at sunrise she turns from a distant rocket toward the camera, smiles and waves while the wind moves her hair.
Prices
What it costs
| Item | Leda Lite | Leda | Leda Pro |
|---|---|---|---|
| 480P output, per second | $0.01 | Not offered | Not offered |
| 768P output, per second | $0.02 | $0.05 | $0.075 |
| 2K output, per second | $0.03 | $0.06 | $0.10 |
| Reference video, per second of output | $0.035 | $0.07 | $0.12 |
| Images included in the price | 5 | 1 | 1 |
| Each further image | $0.01 | $0.13 | $0.25 |
| Reference audio and soundtrack | Free | Free | Free |
- You pay for the requested
duration. - 2K, or 768P with
upscale: true, is billed at the 2K rate; 768P without upscale at the 768P rate. On Leda Lite, 480P withupscale: trueis billed at the 768P rate. - A reference video is trimmed to the output length and billed for the full duration, even if the clip is shorter.
- First, last and keyframe images count as images, the same as references. A text-only clip pays for the output alone.
- Prompt enhancement (
prompt_enhance) is free. - A failed job is free.
- 480P is Leda Lite only. Leda and Leda Pro are 768P and 2K only.
- Tariff version 2026-10-31a.
Examples:
- Leda Pro, 2K, 7 s, one reference video: $0.70 + 7 × $0.12 = $1.54
- Leda Pro, 768P, 5 s, 3 images: $0.375 + 2 × $0.25 = $0.875
- Leda Pro, 768P, 5 s, one reference video and 1 image: $0.375 + 5 × $0.12 = $0.975
- Leda, 768P, 5 s, 3 images: $0.25 + 2 × $0.13 = $0.51
- Leda, 2K, 4 s, one reference video: $0.24 + 4 × $0.07 = $0.52
- Leda Lite, 768P, 4 s, 6 images: $0.08 + $0.01 = $0.09
- Leda, 768P, 5 s, first and last frame: $0.25 + $0.13 = $0.38
- Leda Pro, 768P, 5 s, first and last frame: $0.375 + $0.25 = $0.625
- Leda Lite, 2K, 8 s, text only or with your own soundtrack: 8 × $0.03 = $0.24
- Leda Lite, 480P, 8 s, one first frame: 8 × $0.01 = $0.08
Content rules
- No real people without their consent. Upload photos or voice recordings of a real, identifiable person, or ask for their likeness or voice, only if you have their permission.
- No sexual or explicit content.
- No minors: no images of children as references and nothing that sexualizes or endangers minors.
- We may block requests and close accounts that break these rules. Full terms: Terms of Service and Privacy Policy
FAQ
Questions
What does it cost?
You pay per second of output video. Leda Lite: $0.01 at 480P, $0.02 at 768P and $0.03 at 2K. Leda: $0.05 at 768P and $0.06 at 2K. Leda Pro: $0.075 at 768P and $0.10 at 2K. A reference video adds $0.035 (Leda Lite), $0.07 (Leda) or $0.12 (Leda Pro) per second of output. Leda Lite includes 5 images, Leda and Leda Pro 1 each; each further image is $0.01 (Leda Lite), $0.13 (Leda) or $0.25 (Leda Pro). Reference audio and your own soundtrack are free, and a failed job is not charged. See Prices.
Leda Lite, Leda or Leda Pro?
Leda Lite takes seconds and is right for most drafts and social clips: it is a version of the model our team optimized for speed and lower cost. Leda is the middle option, priced between the two. Leda Pro is optimized too, with minimal loss of quality, and stays closest to the original release; it takes about four to seven times longer. Text only, first and last frame, keyframes and your own soundtrack work in all three.
Is 2K generated at 2K?
No. The model generates at 768P, and the upscaler built into Sociaro Leda doubles each side from that original output, adding sharpness and bringing out fine details. Choose 768P if you want the model's own output without the upscale.
How long will I wait?
On Leda Lite a 5-second 768P clip takes about 11 seconds and a 15-second 2K clip about a minute. With one reference, a 5 s Leda Pro clip takes about 1 min 20 s and a 15 s 2K clip about 4 min 30 s; requests with many references near the limit take up to about 9 minutes. At busy times it can take longer.
Is there an API?
Yes: a simple jobs API, one request to create a job, then polling or a callback. See For developers.
For developers
Jobs API reference
Create a job with one request, then poll it or receive a callback when the MP4 is ready.
Base URL and authentication
| Method | Path | Description |
|---|---|---|
| POST | /v2/jobs | Create a job. 202 with id and status: "queued". A retry with the same Idempotency-Key and body returns 200 and the existing job. |
| GET | /v2/jobs/{id} | Get a job. 200 with the job object: status, output URL and cost. |
| POST | /v2/jobs/{id}/cancel | Cancel a job that has not started. 200 with the job object, now canceled and not charged. A final job comes back unchanged. A running job cannot be canceled: 409 cancel_not_supported. |
| GET | /v2/models | List all models served on /v2, including the three Leda models. 200 with {"data": [...]}: one entry per model, with id, media and input_schema, the JSON Schema of input. |
# create: one reference image, 16:9, 768P, 10 seconds
curl https://api.sociaro.com/v2/jobs \
-H "Authorization: Bearer $SOCIARO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: shot-0042" \
-d '{
"model": "sociaro/leda-lite",
"input": {
"prompt": "The woman in the reference picture turns toward the window and smiles; soft morning light, distant traffic.",
"reference_image_urls": ["https://your-cdn.example.com/reference.png"],
"duration": 10,
"resolution": "768P",
"ratio": "16:9"
}
}'
# response: 202 Accepted
{
"id": "job_0123456789abcdef0123456789abcdef",
"model": "sociaro/leda-lite",
"status": "queued",
"created_at": "2026-10-30T10:05:04.110366+00:00"
}
Full reference headers, request body, input fields, limits, frames, content parts, job object, statuses, callback, errors, examples
Request headers
| Header | Applies to | Required | Value and behavior |
|---|---|---|---|
Authorization | All requests | Required | Bearer <API key>. A missing, invalid or expired key returns 401 invalid_key. |
Content-Type | POST /v2/jobs | Recommended | application/json |
Idempotency-Key | POST /v2/jobs | Required | Your unique id for this job: 1 to 255 characters from A-Z a-z 0-9 . _ : -. Retry with the same key and the same body to get the existing job (200) instead of a second job. The same key with a different body returns 409 idempotency_conflict. callback_url is not part of the comparison. |
Response header Retry-After: 5 comes with GET /v2/jobs/{id} while the job is queued or running, and with 429 too_many_inflight_jobs: wait that many seconds before the next request.
Request body
POST /v2/jobs takes a JSON object. It is closed: an unknown top-level field returns 400 invalid_input.
| Field | Type | Required | Values and behavior |
|---|---|---|---|
model | string | Required | "sociaro/leda-lite", "sociaro/leda" or "sociaro/leda-pro". The earlier ids sociaro/leda-fast, sociaro/leda-balanced and sociaro/leda-quality still work as deprecated aliases. |
input | object | Required | Generation parameters. See Input fields. |
prompt_enhance | string | null | Optional | "off" (default), "basic" or "full", lowercase; null means "off". Expands the prompt before generation. Free: nothing is added to cost_usd. |
callback_url | string | null | Optional | An https URL on a public host. When the job succeeds or fails, we send one POST with the job object to it. See Callback. Omit it or send null for no callback; an empty string is rejected. |
Input fields
| Field | Type | Required | Values, default and rules |
|---|---|---|---|
prompt | string | Conditional | Required in the flat form: not empty, up to 7000 characters. In the content form, send it as the text part instead. |
reference_image_urls | string[] | Conditional | 1 to 9 URLs. HEIC and HEIF (.heic, .heif) are rejected. Omit the field rather than send []. |
reference_video_urls | string[] | Conditional | 1 to 3 URLs, each video 2 to 15 s, at most 15 s together. How many fit depends on the model and the duration: see Limits. |
reference_audio_urls | string[] | Optional | 1 to 3 URLs. Only together with an image or a video. |
first_frame_url | string | Optional | The clip starts on this image. Not together with any reference_*_urls field. |
last_frame_url | string | Optional | The clip ends on this image. Not together with any reference_*_urls field. |
keyframes | object[] | Optional | 1 to 9 objects {"url": "https://...", "frame": 62}, no other keys. Each image is pinned to that frame. See Frames, keyframes, soundtrack. |
soundtrack_url | string | Optional | MP3 or WAV, 2 to 15 s, up to 15 MiB. The clip's sound is this track. Not together with keyframes, a reference video or reference audio. |
content | array | Alternative | Replaces prompt and the media fields above. See Advanced: content parts. |
duration | integer | Required | Output length in seconds, 4 to 15. A JSON integer: 10.0 and "10" are rejected. Billed as requested; 4 renders 124 frames at 24 fps, about 5.2 s. |
resolution | string | Required | "768P" or "2K", and "480P" on Leda Lite only (for drafts: the model was trained at 768P). 2K is the 768P output upscaled x2. Pixel sizes: Formats. |
ratio | string | Optional | "adaptive" (default), "21:9", "16:9", "4:3", "1:1", "3:4" or "9:16". Text only, and a soundtrack without an image, need a named ratio. "adaptive" follows the first frame, else the last frame, else the earliest keyframe; beside references, your first reference. |
upscale | boolean | Optional | true upscales x2: 768P bills at the 2K rate, 480P (Leda Lite) at the 768P rate. "2K" with false is rejected. |
seed | integer | string | Optional | Integer from 0 to 9007199254740991, or a string of 1 to 20 digits up to 18446744073709551615. Random if omitted. The job object does not return the seed: send your own to reproduce a result. |
aigc_watermark | boolean | Optional | Only false is accepted. |
inputis closed: any field not listed above returns400 invalid_input.- Use the flat fields (
promptand the media fields) orcontent, not both. Mixing them returns400. - A prompt alone works (text only), with a named
ratio. - Deprecated synonyms, still accepted with the same values:
enhanceforupscale, andextra.prompt_expansion_modeforprompt_enhance. If both names are sent, they must agree; otherwise the request returns400. - Media URLs (references, frames, keyframes, soundtrack): https, a public host with an ASCII hostname, port 443 or none, no user name or password, no
#fragment, no backslash or control characters, up to 8192 characters each.
Limits
- Media: up to 12 per job, with at most 9 images (references, frames and keyframes together), 3 videos and 3 audio clips (a soundtrack counts).
- Reference audio: only together with an image or a video.
- References per job: how many images and videos fit depends on the model and the duration; see the tables. Leda Lite and Leda count every reference video as if it ran the whole
durationand every image at its largest size. One reference image alone always fits. - Video and audio length: each reference video and audio track is 2 to 15 s long; together the reference videos may last at most 15 s, and the audio tracks too. Outside that, Leda Pro refuses the request when the job is created (
400); Leda Lite and Leda end the jobfailed(error.codeprovider_failed,provider_codeinvalid_input), not charged. - Prompt: up to 7000 characters.
- Length: the references, the prompt and the duration share one limit, checked when the job is created. Over it, the request returns
400 invalid_input. The tables show what fits with a prompt of up to 400 bytes (UTF-8).
| Duration | Images | Videos | One video + images |
|---|---|---|---|
| 4 to 5 s | 9 | 3 | 1 + 9 |
| 6 to 7 s | 9 | 2 | 1 + 9 |
| 8 to 10 s | 9 | 1 | 1 + 9 |
| 11 to 15 s | 9 | None | None |
| Duration | Images | Videos | One video + images |
|---|---|---|---|
| 4 to 5 s | 9 | 3 | 1 + 9 |
| 6 to 8 s | 9 | 2 | 1 + 9 |
| 9 to 13 s | 9 | 1 | 1 + 9 |
| 14 s | 9 | 1 | 1 + 8 |
| 15 s | 9 | 1 | 1 + 4 |
| Duration | Images | Videos | One video + images |
|---|---|---|---|
| 4 to 5 s | 6 | 3 | 1 + 4 |
| 6 to 7 s | 6 | 2 | 1 + 3 |
| 8 s | 5 | 1 | 1 + 2 |
| 9 s | 5 | 1 | 1 + 1 |
| 10 s | 5 | 1 | the video alone |
| 11 to 12 s | 4 | None | None |
| 13 to 15 s | 3 | None | None |
On Leda a reference image with one keyframe fits at every length; more keyframes add to the count.
| Duration | Reference images 16:9 / 1:1 / 2.5:1 | Reference videos of 5 s | One 5 s video + images 16:9 / 2.5:1 | One reference video, up to |
|---|---|---|---|---|
| 4 to 5 s | 7 / 9 / 5 | 3 | 1 + 5 / 1 + 3 | 15 s |
| 6 to 7 s | 6 / 9 / 4 | 2 | 1 + 4 / 1 + 3 | 15 s |
| 8 s | 6 / 9 / 4 | 2 | 1 + 4 / 1 + 2 | 15 s |
| 9 s | 5 / 9 / 4 | 2 | 1 + 3 / 1 + 2 | 15 s |
| 10 s | 5 / 9 / 3 | 2 | 1 + 3 / 1 + 2 | 15 s |
| 11 s | 5 / 8 / 3 | 2 | 1 + 2 / 1 + 1 | 10.8 s |
| 12 s | 4 / 8 / 3 | 2 | 1 + 2 / 1 + 1 | 10.1 s |
| 13 s | 4 / 7 / 3 | 1 | 1 + 1 / 1 + 1 | 9.4 s |
| 14 s | 3 / 7 / 2 | 1 | 1 + 1 / 1 + 1 | 8.7 s |
| 15 s | 3 / 6 / 2 | 1 | 1 + 1 / the video alone | 8 s |
- With a prompt of up to 400 bytes. Leda Pro counts each reference image at its own size and each reference video at its own length. Anything past the table returns
400 invalid_inputwhen the job is created. - When a request fits only at the real sizes, we read each file's header as the job is created. A reference we cannot read there (another format, a fragmented MP4, a URL that redirects or does not answer in time) makes the request a
400, and no job is created. - A video longer than the clip is cut to it. One reference image alone always fits. First, last and keyframe images are not references: they count at a smaller size, and every combination of them fits at every length on Leda Pro.
Frames, keyframes, soundtrack
Every Leda model: Leda Lite, Leda and Leda Pro. 768P and 2K (and 480P on Leda Lite), 4 to 15 s, as everywhere.
| Mode | Flat form | Content role | Goes with |
|---|---|---|---|
| Text only | prompt alone | the text part alone | a named ratio, not "adaptive" |
| First frame | first_frame_url | first_frame | last frame, keyframes or a soundtrack; never a reference |
| Last frame | last_frame_url | last_frame | first frame, keyframes or a soundtrack; never a reference |
| Keyframes | keyframes | sociaro_keyframe with frame | first and last frame, or reference images; never a reference video, reference audio or a soundtrack |
| Soundtrack | soundtrack_url | sociaro_target_audio | first and last frame, or reference images; never a reference video, reference audio or keyframes. Without an image, a named ratio |
- Frames:
frameis a frame of the output at 24 fps, from 0. A clip has N frames: 124 at 4 and 5 s, 158 at 6 s, 175 at 7 s, 192 at 8 s, 226 at 9 s, 243 at 10 s, 277 at 11 s, 294 at 12 s, 328 at 13 s, 345 at 14 s, 362 at 15 s. A negative frame counts from the end:-1is the last. - Keyframes: without reference images a keyframe sits on 1 to N‑2, since the first and last frames belong to the first and last frame images. Beside reference images it may sit on 0 to N‑1. One keyframe per frame:
62and-62are the same frame of a 5 s clip. A JSON integer only:62.0is rejected. - Images: at most 9 in all, first and last frame plus keyframes, or reference images plus keyframes. At most one first frame, one last frame and one soundtrack.
- Soundtrack: MP3 or WAV, 2 to 15 s, up to 15 MiB. A longer track is cut to the clip, a shorter one ends in silence. The track is checked after the job is accepted: a track outside these limits ends the job
failed(error.codeprovider_failed,provider_codeinvalid_input), not charged. - Long clips: frame and keyframe images share the length limit with the prompt. With a prompt of up to 400 bytes, all 9 fit at every length on every model.
# Leda Lite: first and last frame plus one keyframe, 5 s
{
"model": "sociaro/leda-lite",
"input": {
"prompt": "The paper boat from the first frame drifts under the bridge of the last frame; rain, distant traffic.",
"first_frame_url": "https://your-cdn.example.com/first.jpg",
"last_frame_url": "https://your-cdn.example.com/last.jpg",
"keyframes": [{"url": "https://your-cdn.example.com/mid.jpg", "frame": 62}],
"duration": 5,
"resolution": "768P"
}
}
# Leda: first frame and your own soundtrack
{
"model": "sociaro/leda",
"input": {
"prompt": "A dancer in the warehouse moves to the beat.",
"first_frame_url": "https://your-cdn.example.com/dancer.jpg",
"soundtrack_url": "https://your-cdn.example.com/track.mp3",
"duration": 8,
"resolution": "2K"
}
}
Advanced: content parts
An alternative to the flat fields: the content form puts the prompt and the media into one ordered array, input.content. Use it when you need to set the order of the parts.
- 1 to 13 parts: exactly one
textpart and up to 12 media parts. - Each part takes only the keys shown.
roleis required and must match the type. - Parts keep the order you send. The flat form is the same as text first, then images, videos and audio.
duration,resolution,ratio,upscale,seedandaigc_watermarkstay ininputas usual.
# input.content: replaces prompt and the media fields
"content": [
# exactly 1
{"type": "text", "text": "..."},
# up to 9
{"type": "image_url", "image_url": {"url": "https://..."},
"role": "reference_image"},
# up to 3
{"type": "video_url", "video_url": {"url": "https://..."},
"role": "reference_video"},
# up to 3
{"type": "audio_url", "audio_url": {"url": "https://..."},
"role": "reference_audio"},
# at most 1 each
{"type": "image_url", "image_url": {"url": "https://..."},
"role": "first_frame" | "last_frame"},
# frame is required
{"type": "image_url", "image_url": {"url": "https://..."},
"role": "sociaro_keyframe", "frame": 62},
# your soundtrack, at most 1
{"type": "audio_url", "audio_url": {"url": "https://..."},
"role": "sociaro_target_audio"}
]
Job object
Returned by GET /v2/jobs/{id}, by a create retry with the same Idempotency-Key, and sent to callback_url. A field without a value is omitted, never null. The job object does not echo the input: no prompt, references, seed, resolution or duration.
| Field | Type | Present | Description |
|---|---|---|---|
id | string | Always | job_ followed by 32 hex characters. |
status | string | Always | See Statuses. |
model | string | Always | The model id from the request. |
media | string | Always | "video" |
created_at | string | Always | ISO 8601 in UTC, for example 2026-10-30T10:05:04.110366+00:00. |
deadline_at | string | Always | created_at plus 48 minutes. A job not finished by then becomes expired. |
retention_until | string | Always | created_at plus 30 days. After that, GET no longer lists outputs and can return 404. |
completed_at | string | Final status | When the job finished. |
cost_usd | number | succeeded | Amount charged in USD. See Prices. |
outputs | array | succeeded | The result: one video. |
outputs[].url | string | succeeded | MP4 link on https://cdn.sociaro.com. Store it: the link works until expires_at, after the job record is gone. |
outputs[].type | string | succeeded | "video" |
outputs[].content_type | string | succeeded | "video/mp4" |
outputs[].expires_at | string | succeeded | About 10 years after the job finished. |
outputs[].width, .height | integer | If known | Size in pixels, for example 1344 and 768. |
outputs[].duration_sec | number | If known | Actual length in seconds, for example 5.1667 for duration: 4. |
error | object | failed, canceled, expired | {"code": "...", "message": "..."}, plus provider_code when the generator reported one. |
retry_after | integer | queued, running | 5: seconds to wait before the next poll, same as the Retry-After header. |
cancel_requested | boolean | After a cancel, not final | true when a cancel arrived while the job was being started. Keep polling: the job ends as canceled or with its normal result. |
Statuses
| Status | Final | Billed | Meaning |
|---|---|---|---|
queued | No | No | Accepted, waiting to start. |
running | No | No | Generating. |
succeeded | Yes | Yes | The MP4 is at outputs[0].url; the amount charged is in cost_usd. |
failed | Yes | No | Generation did not finish. error.code is provider_failed, provider_rejected, quota_exceeded, output_too_large, unsupported_media or internal. |
canceled | Yes | No | Canceled with POST /v2/jobs/{id}/cancel before it started. error.code is canceled. |
expired | Yes | No | Not finished by deadline_at. error.code is expired. |
Callback
With callback_url set, we send one POST to that URL when the job succeeds or fails. The JSON body is the job object, the same one GET returns, and the header Idempotency-Key: <job id> lets you drop duplicates.
- One attempt, 15 second timeout, no retries. The request is not signed.
- A callback is sent when the job ends
succeededorfailed(any code). A job canceled withPOST /cancel, orexpired, sends none. Keep a fallback poll ofGET /v2/jobs/{id}, at the latest afterdeadline_at. - The URL must use https, and its host must resolve only to public addresses.
Errors
Errors return a JSON body {"error": {"code": "...", "message": "..."}}. Branch on code; message is for people and names the exact problem.
| HTTP | error.code | Meaning |
|---|---|---|
| 400 | idempotency_key_required | The Idempotency-Key header is missing. |
| 400 | invalid_idempotency_key | The key is not 1 to 255 characters of A-Z a-z 0-9 . _ : -. |
| 400 | invalid_input | Invalid JSON, an unknown or missing field, a value out of range, or a request over the length limit. |
| 400 | invalid_callback_url | callback_url is not https, or its host is not allowed. |
| 401 | invalid_key | The API key is missing, invalid or expired. |
| 403 | forbidden | The key may not use this API or this model. |
| 404 | model_not_found | Unknown model. |
| 404 | job_not_found | No job with this id on your account. |
| 409 | idempotency_conflict | The Idempotency-Key was already used with a different body. |
| 409 | cancel_not_supported | The job is already running and cannot be canceled. |
| 429 | insufficient_budget | The account balance is used up, or the key's rate limit is reached. The message says which. |
| 429 | too_many_inflight_jobs | Too many jobs queued or running. Retry after Retry-After (5 s). The error also carries scope ("tenant" or "key") and retry_after. |
| 502 | upstream_error | The key check could not complete. Retry. |
| 503 | unavailable | The service is temporarily not accepting jobs. Retry later. |
Examples
# poll every Retry-After seconds until final
curl https://api.sociaro.com/v2/jobs/$JOB_ID \
-H "Authorization: Bearer $SOCIARO_API_KEY"
# 200: a finished Leda Lite job, duration 4, 768P, 16:9
{
"id": "job_0123456789abcdef0123456789abcdef",
"status": "succeeded",
"model": "sociaro/leda-lite",
"media": "video",
"created_at": "2026-10-30T10:05:04.110366+00:00",
"deadline_at": "2026-10-30T10:53:04.110366+00:00",
"retention_until": "2026-11-29T10:05:04.110366+00:00",
"completed_at": "2026-10-30T10:06:20.033665+00:00",
"cost_usd": 0.08,
"outputs": [{
"url": "https://cdn.sociaro.com/v2/job_0123.../0-....mp4",
"type": "video",
"content_type": "video/mp4",
"expires_at": "2036-10-30T10:06:20.021745+00:00",
"width": 1344,
"height": 768,
"duration_sec": 5.166666666666667
}]
}
# Python 3 with requests: create a job, then poll it
import os, time, uuid
import requests
API = "https://api.sociaro.com/v2/jobs"
KEY = os.environ["SOCIARO_API_KEY"]
AUTH = {"Authorization": f"Bearer {KEY}"}
body = {
"model": "sociaro/leda-lite",
"input": {
"prompt": "The woman in the reference picture "
"turns toward the window and smiles.",
"reference_image_urls": [
"https://your-cdn.example.com/reference.png"],
"duration": 10,
"resolution": "768P",
"ratio": "16:9",
},
}
# keep this key if you retry the POST: no duplicate job
idem = str(uuid.uuid4())
r = requests.post(API, json=body, timeout=30,
headers={**AUTH, "Idempotency-Key": idem})
r.raise_for_status()
job = r.json()
# poll until the status is final
while job["status"] in ("queued", "running"):
time.sleep(int(r.headers.get("Retry-After", 5)))
r = requests.get(f"{API}/{job['id']}", headers=AUTH,
timeout=30)
r.raise_for_status()
job = r.json()
if job["status"] == "succeeded":
print(job["outputs"][0]["url"], job["cost_usd"])
else:
print(job["status"], job["error"]["code"])