Halloween sale ยท up to 40% off your first month + bonus credits, claimable daily

Claim it

Official BytePlus partnerBytePlus, a ByteDance company

Seedance API reference

Everything a Seedance video job takes and returns on the KreatorFlow API: request fields, the job object, webhooks, uploads, rate limits and error codes. Prepaid tokens at $0.05, top-ups from $20.

  • Base URL https://kreatorflow.ai/v1
  • Bearer API key
  • JSON
  • Idempotency-Key
On this page
  1. Authentication
  2. POST /v1/videos
  3. Response and the job object
  4. GET /v1/jobs/{id}
  5. Webhooks
  6. Uploads and references
  7. Rate limits
  8. Error codes
  9. Keep going

Authentication

Send your key as Authorization: Bearer KREATORFLOW_API_KEY on every request to https://kreatorflow.ai/v1. Keys are created in the API console and carry scopes, for example videos:create. Keep the key on your server, never in a browser or app.

Add an Idempotency-Key header to every create. If a request times out, send it again with the same key and you get the original job back instead of a second one.

POST /v1/videos

Creates a Seedance video job. The price is quoted and reserved before the job is accepted.

FieldTypeDescription
modelstringModel alias, for example kreator-video-seedance-2-5, kreator-video-pro (Seedance 2.0), kreator-video-fast or kreator-video-mini. Defaults to kreator-video-fast.
promptrequiredstringWhat should happen in the clip: subject, action, camera move, light and style.
durationnumberLength in seconds. Must be one of the model's durations (GET /v1/models lists them).
resolutionstring480p, 720p, 1080p or 4k, where the model offers it.
aspect_ratiostringFor example 16:9, 9:16, 1:1, 4:3, 3:4 or 21:9. ratio is accepted as an alias.
generate_audiobooleanGenerate sound with the clip on models that support it.
seedintegerFix the seed to get a similar result from the same request.
camera_fixedbooleanKeep the camera still. Leave it out when you send image or frame inputs.
watermarkbooleanDefaults to false.
first_frame_url / first_frame_upload_idstringAn image the clip starts on (public HTTPS URL or an upload id).
last_frame_url / last_frame_upload_idstringAn image the clip ends on. Send it with a first frame for a transition.
reference_image_urls / reference_image_upload_idsstring[]Images that guide the look of a product, character, outfit or style.
reference_video_urls / reference_video_upload_idsstring[]Clips that guide motion or camera work.
reference_audio_urls / reference_audio_upload_idsstring[]Audio that guides voice, music or timing.
character_idsstring[]Reusable characters registered once with POST /v1/characters.
webhook_urlstringHTTPS URL that receives a signed event when the job ends. callback_url is accepted as an alias.
curl https://kreatorflow.ai/v1/videos \
  -H "Authorization: Bearer $KREATORFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: perfume-teaser-001" \
  -d '{
    "model": "kreator-video-seedance-2-5",
    "prompt": "slow dolly in on a glass perfume bottle on wet black stone, soft studio light, light rain",
    "duration": 5,
    "aspect_ratio": "9:16",
    "resolution": "720p"
  }'

# then poll until status is completed, failed, canceled or blocked
curl https://kreatorflow.ai/v1/jobs/JOB_ID \
  -H "Authorization: Bearer $KREATORFLOW_API_KEY"

Limits differ by model. The Seedance 2.5 API, Seedance 2.0 API, Seedance 2.0 Fast API and Seedance 2.0 Mini API pages list the durations, resolutions, reference limits and price of each.

Response and the job object

A create returns the job, the quoted cost and your remaining balance.

{
  "success": true,
  "data": {
    "job": {
      "id": "3f0c0e0a-0000-4000-8000-000000000000",
      "mediaType": "video",
      "modelId": "kreator-video-fast",
      "status": "processing",
      "quotedTokenCost": 9,
      "finalTokenCost": 0,
      "providerOutputUrl": null,
      "errorCode": null,
      "errorMessage": null,
      "createdAt": "2026-10-17T12:00:00.000Z",
      "completedAt": null
    },
    "quoted_token_cost": 9,
    "balance_tokens": 391
  }
}
FieldTypeDescription
idstringJob id. Use it with GET /v1/jobs/{id}.
statusstringOne of created, queued, processing, completed, failed, canceled, blocked. completed, failed, canceled and blocked are final.
modelIdstringThe model alias the job ran on.
quotedTokenCostnumberTokens reserved when the job was accepted (1 token = $0.05).
finalTokenCostnumberTokens charged. 0 for a job that failed, so nothing is charged for failed work.
providerOutputUrlstring | nullDownload link for the finished file. It needs your API key and expires, so copy the file to your own storage.
errorCode / errorMessagestring | nullWhy a job failed (see the error codes below).
createdAt / completedAtstringISO timestamps.

GET /v1/jobs/{id}

Poll a job until its status is final, or use a webhook instead.

{
  "success": true,
  "data": {
    "job": {
      "id": "3f0c0e0a-0000-4000-8000-000000000000",
      "status": "completed",
      "quotedTokenCost": 9,
      "finalTokenCost": 9,
      "providerOutputUrl": "https://kreatorflow.ai/v1/jobs/3f0c0e0a-0000-4000-8000-000000000000/output",
      "providerOutputExpiresAt": "2026-10-24T12:00:00.000Z",
      "errorCode": null,
      "completedAt": "2026-10-17T12:01:10.000Z"
    }
  }
}

Poll every 10 to 15 seconds for video. GET /v1/jobs/{id}/output downloads the file with the same key; the link expires, so copy each finished file to your own storage (see storing and delivering AI video).

Webhooks

Pass webhook_url and KreatorFlow posts job.completed, job.failed, job.canceled or job.blocked when the job ends.

{
  "object": "kreatorflow.developer_webhook_event",
  "id": "evt_<job_id>_completed",
  "type": "job.completed",
  "created": "2026-10-17T12:01:10.000Z",
  "data": {
    "job": {
      "id": "<job_id>",
      "status": "completed",
      "providerOutputUrl": "https://kreatorflow.ai/v1/jobs/<job_id>/output"
    }
  }
}

Each event carries X-KreatorFlow-Event-Id, X-KreatorFlow-Event-Type, X-KreatorFlow-Job-Id, X-KreatorFlow-Timestamp and X-KreatorFlow-Signature. Check the signature with the secret from the Webhooks tab, and use the event id to ignore an event you have already handled. Answer with a 2xx quickly and do the work afterwards.

import { createHmac, timingSafeEqual } from "node:crypto";

// rawBody: the request body exactly as received (a string, before JSON.parse)
export function verifyKreatorFlowWebhook(rawBody, signatureHeader, secret) {
  const parts = Object.fromEntries(signatureHeader.split(",").map((part) => part.split("=")));
  const expected = createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300; // reject replays older than 5 min
  return fresh && expected.length === parts.v1?.length && timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}

The full walkthrough is in AI video API webhooks.

Uploads and references

References can be public HTTPS URLs or files you upload. To upload: POST /v1/uploads with the file name, type and size, PUT the bytes to the returned direct_upload_url with the returned headers, then POST /v1/uploads/complete. Pass the upload_id in any reference field. Size limits: images 50 MB, video 200 MB, audio 15 MB.

References must be media you own or have permission to use. A photo of a real person is declined as a reference; register an owned character with POST /v1/characters instead.

Rate limits

Per developer account. A 429 response carries a Retry-After header with the seconds to wait.

POST /v1/uploads60 per minute
PUT /v1/uploads60 per minute
DELETE /v1/uploads/{upload_id}60 per minute
POST /v1/videos20 per minute
GET /v1/jobs/{job_id}120 per minute
GET/HEAD /v1/jobs/{job_id}/output300 per minute

Error codes

Request errors fail the HTTP call itself. Job errors end a job as failed, and its reserved tokens are released.

Request errors

CodeStatusMeaningWhat to do
invalid_api_key401The key is missing, wrong or revoked.Send Authorization: Bearer <key>. Create a new key if it was revoked.
insufficient_balance402Not enough tokens for the quoted cost.Top up under Billing. data.top_up_url links there.
account_not_active403The developer account is suspended.Contact support.
scope_missing403The key lacks the scope this endpoint needs.Use a key with that scope.
job_not_found404No job with that id for this key's account.Check the id; jobs are private to the account.
character_not_found404The character id or slug doesn't exist.List characters with GET /v1/characters.
upload_not_found404The upload_id doesn't exist in this workspace.Create the upload again.
reference_upload_not_found404A reference upload_id doesn't exist in this workspace.Re-upload the file and use the new upload_id.
video_edit_source_not_found404The source_video_upload_id doesn't exist.Upload the clip with upload_type VIDEO.
upload_in_use409A queued or processing job still uses this upload.Delete it after the job finishes.
character_pending409The character is still being reviewed. Nothing was reserved.Wait retry_after seconds, then retry.
upload_too_large413The file is over the size limit for its type.Images 50 MB, video 200 MB, audio 15 MB.
character_registration_failed422The character image did not pass review.Register the character again with another image.
rate_limited429Too many requests in the window.Wait the seconds in the Retry-After header.
prompt_required400No prompt (or text for speech) was sent.Add a prompt.
prompt_too_long400The prompt is over the model's limit.Shorten it; GET /v1/models lists maxPromptChars.
model_not_found400Unknown model alias.Use an id from GET /v1/models.
duration_not_supported400The model doesn't offer that length.Send one of the model's durations.
aspect_ratio_not_supported400The model doesn't offer that aspect ratio.Send one of the model's aspect ratios.
resolution_not_supported400The model doesn't offer that resolution.Send one of the model's resolutions.
reference_combination_not_supported400These references can't be combined, e.g. start/end frames with reference images.Send one kind per request.
character_prompt_unsafe400A character prompt asks to match a real person.Describe appearance, wardrobe, pose and style instead.
person_match_prompt_unsafe400A reference prompt asks to match a real person's face or likeness.Register an owned character and describe the look instead.
upload_invalid400The upload request is missing a field or has a bad type.Send file_name, mime_type, file_size and upload_type.
video_edit_model_not_supported400Video edits need a Seedance 2.0 family model (2.0, Fast or Mini).Use kreator-video-pro, kreator-video-fast or kreator-video-mini.
video_edit_source_required400A video edit needs a source clip.Send source_video_upload_id or video.
voice_required400Speech needs a voice.Use an id from GET /v1/voices.
internal_error500Something failed on our side.Retry with the same Idempotency-Key.
dispatch_disabled503Generation is paused for this environment.Retry later.

Job errors

CodeStatusMeaningWhat to do
reference_rejectedjobA reference was declined (often a real person's photo).Register the face as a character, or use another image.
reference_asset_pendingjobA new reference is still being reviewed.Wait errorData.retry_after seconds, resubmit with the same upload_id and a new Idempotency-Key.
reference_asset_failedjobThe reference did not pass review.Use a different file.
generation_rejectedjobThe request was declined (prompt, reference or options).Change the prompt, reference or options, then retry.
generation_timeoutjobThe job did not finish in time. Reserved tokens are released.Retry with a new Idempotency-Key.
generation_unavailablejobThe model is temporarily unavailable.Retry later or pick another model.
generation_failedjobThe generation failed.Retry; change the prompt or references if it repeats.

Keep going