API v1

Quickstart

Generate your first video in three steps: create an API key, submit a task, get the result.

View Markdown
On this page

You need an opened account with enough balance to reserve one generation. The example below is a Seedance 2.0 text-to-video request with the default duration, resolution and aspect ratio (5 seconds, 720p, adaptive).

API address

Reading the API address…

Every request path follows this address, for example POST /v1/video/generations. The examples read it from the CHENVOYA_BASE_URL environment variable, without a trailing slash.

Create an API key

On the API keys page of the console, choose Create API key, then save it and the API address above in environment variables on your server. One API key works with every model.

Environment
export CHENVOYA_BASE_URL="your-api-address"
export CHENVOYA_API_KEY="your-api-key"

Warning: Use API keys on servers only. Never put one in a web page, an app or a code repository, or paste it into documents or logs. If you suspect a leak, suspend the key in the console and create a new one.

Submit a generation task

Send the model and the prompt to POST /v1/video/generations. Give every creation a new Idempotency-Key: if the request times out or the connection drops, retry with the same key and body to get exactly one task and one charge.

IDEMPOTENCY_KEY=${IDEMPOTENCY_KEY:-$(uuidgen)}
printf '%s\n' "Save IDEMPOTENCY_KEY for retries: ${IDEMPOTENCY_KEY}" >&2
curl --request POST "${CHENVOYA_BASE_URL}/v1/video/generations" \
  --header "Authorization: Bearer ${CHENVOYA_API_KEY}" \
  --header "Idempotency-Key: ${IDEMPOTENCY_KEY}" \
  --header 'Content-Type: application/json' \
  --data '{
  "model": "dreamina-seedance-2-0-260128",
  "content": [
    {
      "type": "text",
      "text": "A paper boat crossing a moonlit lake."
    }
  ]
}'

The API answers at once with 202 and the task ID; generation runs in the background.

Response202Excerpt
{
  "id": "task_32ae2a5177b310d3bc1ec83a98f63889",
  "object": "video.task",
  "model": "dreamina-seedance-2-0-260128",
  "status": "queued",
  "settlement_status": "reserved",
  "quote": {
    "currency": "USD",
    "reserved_amount": "0.782453",
    "estimated_usage_upper_bound": {
      "video_tokens": 111779
    }
  },
  "created_at": 1793167380
}

Note: Funds for the request's upper bound are reserved first (quote.reserved_amount). After completion the task is settled on actual usage and the rest is released; failed and cancelled tasks are free.

Get the result

A task moves through the states below; succeeded, failed and cancelled are final.

Poll the task

Read GET /v1/video/tasks/{task_id} every few seconds until status is final.

curl --request GET "${CHENVOYA_BASE_URL}/v1/video/tasks/${TASK_ID}" \
  --header "Authorization: Bearer ${CHENVOYA_API_KEY}"
Response200Excerpt
{
  "id": "task_32ae2a5177b310d3bc1ec83a98f63889",
  "object": "video.task",
  "status": "succeeded",
  "output": {
    "assets": [
      {
        "media_type": "video",
        "role": "result",
        "url": "https://media.example.invalid/download/result-0001?signature=example",
        "expires_at": 1793253785
      }
    ]
  }
}

After success, output.assets[0].url is the download link of the video. It works for up to 24 hours and never after expires_at (7 days after the result is ready by default); query the task again for a fresh link. It is null after expires_at. Save the video to your own storage:

curl --output video.mp4 "$VIDEO_URL"

Receive a callback

Instead of polling, let us notify you: add and verify an HTTPS address on the Callbacks page of the console, then put it in callback_url when you create a task. You receive task.completed when the task finishes and task.billing_settled once its charge is settled. Verify the signature before you handle an event.

"callback_url": "https://example.com/webhooks/chenvoya"

Next steps