roasOS
Workflows

Animate a still

Turn one still image into one video.

Animate a still turns one image that your workspace owns into one image-to-video generation. Use it on a product photo, on a static ad, or on any still that you already made with roasOS.

One call makes one video. There is no fan-out, and there is no variants field.

1. Choose the still

Send exactly one source.

FieldUse it for
image_urlA still on https://cdn.roasos.com that your workspace owns
upload_idThe id that POST /v1/uploads gave you

The still must be 10 MB or smaller. Use image/jpeg, image/png or image/webp. Refer to Reference media and uploads.

Add an optional product_id to hold a saved product steady. Its images ride as style references.

2. Write a prompt, or let roasOS write one

Send a prompt that says what moves. Name one primary movement.

The bottle stays still. The steam rises slowly from the cup behind it. The light moves a little across the label.

Set auto_prompt: true to skip that step. roasOS then analyzes the still first and derives the prompt from the analysis.

auto_prompt bills one still analysis on top of the video. That is 1 extra credit. Refer to Analyze an ad.

Send prompt, or set auto_prompt to true. A request with neither is refused.

3. Choose the model

The default is seedance-2.5 (since 2026-10-04). Set model to change it.

ModelUse it for
seedance-2.5The default. It takes its shape from the still, accepts a still that shows a person, and renders one take of up to 30 seconds with sound.
kling-4A still with product references (product_id), or a length that Seedance does not offer.

When you send no model, roasOS uses seedance-2.5. Two exceptions use kling-4: a request with product_id, because Seedance cannot combine a first frame with product references, and a duration_seconds that Seedance does not offer (for example 7). roasOS never changes a model that you sent. With no duration_seconds, the clip is 5 seconds.

The two models accept different options.

Fieldkling-4seedance-2.5
duration_secondsEach whole second from 3 to 304, 5, 6, 8, 10, 12, 15, 20, 25, 30
aspect_ratioTaken from the still; with product_id: 9:16, 16:9, 1:1, 21:9Taken from the still
resolution720p, 1080p; the default is 1080p480p, 720p, 1080p; the default is 720p
prompt length2,500 characters10,000 characters

4. Quote

curl -X POST https://api.roasos.com/v1/workflows/static-to-video \
  -H "Authorization: Bearer roasos_sk_..." \
  -H "Idempotency-Key: animate-serum-hero-001" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://cdn.roasos.com/workspaces/.../serum-hero.png",
    "prompt": "The bottle stays still. The steam rises slowly behind it.",
    "duration_seconds": 5,
    "quote_only": true
  }'
{
  "data": {
    "kind": "quote",
    "quote_id": "f70b2d51-...",
    "credits": 15,
    "expires_at": "2026-08-21T12:09:04.000Z",
    "pricing_version": "customer-pricing@2026-10-30.v14",
    "confirmation": {
      "model": "seedance-2.5",
      "mode": "image-to-video",
      "duration_seconds": 5,
      "generate_audio": true
    }
  }
}

A 5-second Seedance 2.5 clip at 720p costs 15 credits, and a 10-second clip costs 30. On kling-4 at 1080p, the same clips cost 15 and 29 (10 and 19 at 720p). The full table is on the Kling 4.0 page and on the Seedance 2.5 page.

5. Confirm

Send the same body with the quote_id. Use the same idempotency key.

curl -X POST https://api.roasos.com/v1/workflows/static-to-video \
  -H "Authorization: Bearer roasos_sk_..." \
  -H "Idempotency-Key: animate-serum-hero-001" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://cdn.roasos.com/workspaces/.../serum-hero.png",
    "prompt": "The bottle stays still. The steam rises slowly behind it.",
    "duration_seconds": 5,
    "quote_id": "f70b2d51-..."
  }'

The answer is 201 with the standard job envelope.

{
  "data": {
    "id": "1e9c4a70-...",
    "kind": "video",
    "model": "seedance-2.5",
    "status": "queued",
    "credits_reserved": 15,
    "created_at": "2026-08-21T11:59:41Z",
    "links": {
      "self": "/v1/jobs/1e9c4a70-...",
      "status": "/v1/jobs/1e9c4a70-.../status",
      "result": "/v1/jobs/1e9c4a70-.../result",
      "events": "/v1/jobs/1e9c4a70-.../events"
    }
  }
}

6. Poll the job

curl https://api.roasos.com/v1/jobs/1e9c4a70-.../status \
  -H "Authorization: Bearer roasos_sk_..."

Animate a still is an ordinary job, so it carries the five job statuses. Poll every few seconds until the status is completed, failed or canceled. Send a webhook_url in the confirm request when you do not want to poll. Refer to Jobs and to Webhooks.

7. Read the result

curl https://api.roasos.com/v1/jobs/1e9c4a70-.../result \
  -H "Authorization: Bearer roasos_sk_..."
{
  "data": { "url": "https://cdn.roasos.com/workspaces/.../serum-hero.mp4" }
}

Errors

CodeCause
invalid_requestTwo sources, no source, or no prompt and no auto_prompt
reference_media_not_workspace_ownedThe still is not workspace-owned media
provider_rejects_face_referencesThe provider of seedance-2.5 refused a face in the images it received. roasOS refunds the reservation in full.
insufficient_creditsThe balance does not cover the quote
quote_expiredThe quote is older than 10 minutes; quote again under a new idempotency key

Refer to Errors.

From an agent

The MCP tool is roasos_static_to_video. The quote rule is the same. Refer to Connect an AI agent (MCP).

On this page