{
  "openapi": "3.1.0",
  "info": {
    "title": "KreatorFlow API",
    "version": "2026-06-10",
    "summary": "Seedance video, Seedream images, text to speech and lip sync through one REST API.",
    "description": "The KreatorFlow Developer API: ByteDance's Seedance video and Seedream image models, text to speech, sound and lip sync over one REST API with a Bearer API key. KreatorFlow is an official partner of BytePlus, a ByteDance company.\n\nBilling is prepaid tokens at $0.05 each (top-ups from $20); every create response returns the job's quoted cost, and failed jobs release their reserved tokens.\n\nVolume pricing is automatic: Standard: any spend, list price, 20 video requests per minute; Scale: $1,000+ in paid top-ups over 30 days, up to 5% off Seedance video, 60 video requests per minute; Growth: $2,500+ in paid top-ups over 30 days, up to 7.5% off Seedance video, 120 video requests per minute; Enterprise: $5,000+ in paid top-ups over 30 days, up to 10% off Seedance video, 300 video requests per minute. Need more volume? Custom pricing for committed monthly spend: email harry@kreatorflow.ai.\n\nJobs are asynchronous: poll GET /v1/jobs/{job_id} or pass webhook_url to receive a signed event. Prices: https://kreatorflow.ai/seedance-api#volume-pricing. Reference: https://kreatorflow.ai/seedance-api/reference.",
    "contact": {
      "name": "KreatorFlow",
      "url": "https://kreatorflow.ai/developers",
      "email": "harry@kreatorflow.ai"
    },
    "termsOfService": "https://kreatorflow.ai/terms"
  },
  "externalDocs": {
    "description": "Developer docs",
    "url": "https://developers.kreatorflow.ai/?section=docs"
  },
  "servers": [
    {
      "url": "https://kreatorflow.ai",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    },
    {
      "apiKeyHeader": []
    }
  ],
  "tags": [
    {
      "name": "Video"
    },
    {
      "name": "Images"
    },
    {
      "name": "Audio"
    },
    {
      "name": "Lip Sync"
    },
    {
      "name": "Uploads"
    },
    {
      "name": "Jobs"
    },
    {
      "name": "Models"
    },
    {
      "name": "MCP"
    }
  ],
  "paths": {
    "/v1/models": {
      "get": {
        "operationId": "getModels",
        "summary": "Discover model aliases, limits, and clean model names",
        "description": "Discover model aliases, limits, and clean model names.",
        "tags": [
          "Models"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/ModelList"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/uploads": {
      "post": {
        "operationId": "postUploads",
        "summary": "Create a workspace-scoped upload_id for image, video, or audio references",
        "description": "Create a workspace-scoped upload_id for image, video, or audio references. Required scope: uploads:create. Rate limit: 60 per 60 seconds per account.",
        "tags": [
          "Uploads"
        ],
        "x-required-scope": "uploads:create",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UploadCreateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/UploadCreateResponse"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "put": {
        "operationId": "putUploads",
        "summary": "Legacy proxy upload for small reference bytes (<4.5MB); prefer the direct_upload_url flow for larger files",
        "description": "Legacy proxy upload for small reference bytes (<4.5MB); prefer the direct_upload_url flow for larger files. Required scope: uploads:create. Rate limit: 60 per 60 seconds per account.",
        "tags": [
          "Uploads"
        ],
        "x-required-scope": "uploads:create",
        "parameters": [
          {
            "name": "upload_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/uploads/complete": {
      "post": {
        "operationId": "postUploadsComplete",
        "summary": "Finalize and activate an upload whose bytes were PUT to direct_upload_url; returns the ready upload_id",
        "description": "Finalize and activate an upload whose bytes were PUT to direct_upload_url; returns the ready upload_id. Required scope: uploads:create.",
        "tags": [
          "Uploads"
        ],
        "x-required-scope": "uploads:create",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "upload_id"
                ],
                "properties": {
                  "upload_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/UploadCompleteResponse"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/uploads/{upload_id}": {
      "delete": {
        "operationId": "deleteUploadsByUploadId",
        "summary": "Delete an owned developer-API upload (URL-encode the upload_id) and free its bytes from storage usage; 409 upload_in_use while a queued/processing job references it",
        "description": "Delete an owned developer-API upload (URL-encode the upload_id) and free its bytes from storage usage; 409 upload_in_use while a queued/processing job references it. Required scope: uploads:create. Rate limit: 60 per 60 seconds per account.",
        "tags": [
          "Uploads"
        ],
        "x-required-scope": "uploads:create",
        "parameters": [
          {
            "name": "upload_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The upload_id, URL-encoded."
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/storage": {
      "get": {
        "operationId": "getStorage",
        "summary": "Read the workspace's developer-API storage usage: quota_used_bytes (your /v1/uploads, what counts against the quota), included_bytes, used_bytes (everything stored, including outputs), outputs_bytes, has_pack, tier, free_allowance_bytes",
        "description": "Read the workspace's developer-API storage usage: quota_used_bytes (your /v1/uploads, what counts against the quota), included_bytes, used_bytes (everything stored, including outputs), outputs_bytes, has_pack, tier, free_allowance_bytes. Required scope: models:read. Rate limit: 60 per 60 seconds per account.",
        "tags": [
          "Uploads"
        ],
        "x-required-scope": "models:read",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/images": {
      "post": {
        "operationId": "postImages",
        "summary": "Create an image generation job",
        "description": "Create an image generation job. Required scope: images:create. Rate limit: 60 per 60 seconds per account.",
        "tags": [
          "Images"
        ],
        "x-required-scope": "images:create",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImageRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/CreateJobResult"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientBalance"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/characters": {
      "post": {
        "operationId": "postCharacters",
        "summary": "Register a reusable character with mode=register, or create a character-reference image job when a prompt is supplied",
        "description": "Register a reusable character with mode=register, or create a character-reference image job when a prompt is supplied. Required scope: images:create. Rate limit: 60 per 60 seconds per account.",
        "tags": [
          "Images"
        ],
        "x-required-scope": "images:create",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CharacterRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/Character"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "get": {
        "operationId": "getCharacters",
        "summary": "List reusable characters registered for the API key workspace",
        "description": "List reusable characters registered for the API key workspace. Required scope: images:create. Rate limit: 60 per 60 seconds per account.",
        "tags": [
          "Images"
        ],
        "x-required-scope": "images:create",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/characters/{character_id}": {
      "get": {
        "operationId": "getCharactersByCharacterId",
        "summary": "Read one reusable character by id or slug",
        "description": "Read one reusable character by id or slug. Required scope: images:create. Rate limit: 60 per 60 seconds per account.",
        "tags": [
          "Images"
        ],
        "x-required-scope": "images:create",
        "parameters": [
          {
            "name": "character_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/Character"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteCharactersByCharacterId",
        "summary": "Soft-delete one reusable character by id or slug",
        "description": "Soft-delete one reusable character by id or slug. Required scope: images:create. Rate limit: 60 per 60 seconds per account.",
        "tags": [
          "Images"
        ],
        "x-required-scope": "images:create",
        "parameters": [
          {
            "name": "character_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/videos": {
      "post": {
        "operationId": "postVideos",
        "summary": "Create a video generation job",
        "description": "Create a video generation job. Required scope: videos:create. Rate limit: 20 per 60 seconds per account.",
        "tags": [
          "Video"
        ],
        "x-required-scope": "videos:create",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VideoRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/CreateJobResult"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientBalance"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/video-edits": {
      "post": {
        "operationId": "postVideoEdits",
        "summary": "Create a Seedance 2 source-video edit job with transform, restyle, or extend mode",
        "description": "Create a Seedance 2 source-video edit job with transform, restyle, or extend mode. Required scope: videos:create. Rate limit: 20 per 60 seconds per account.",
        "tags": [
          "Video"
        ],
        "x-required-scope": "videos:create",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VideoEditRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/CreateJobResult"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientBalance"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/videos/edit": {
      "post": {
        "operationId": "postVideosEdit",
        "summary": "Edit one clip on Wan 3.0 by instruction (\"make it night\", \"replace the car with Image 1\"), keeping its length",
        "description": "Edit one clip on Wan 3.0 by instruction (\"make it night\", \"replace the car with Image 1\"), keeping its length. Up to 4 reference images. The clip must be uploaded first with POST /v1/uploads (public URLs are not accepted). Billed on the clip's seconds plus the output's, in whole tokens. Required scope: videos:create. Rate limit: 20 per 60 seconds per account.",
        "tags": [
          "Video"
        ],
        "x-required-scope": "videos:create",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VideoToolRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/CreateJobResult"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientBalance"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/videos/extend": {
      "post": {
        "operationId": "postVideosExtend",
        "summary": "Add new footage before, after or on both sides of one clip on Wan 3.0 (at least 2 s added; the clip plus the result stay within 30 s)",
        "description": "Add new footage before, after or on both sides of one clip on Wan 3.0 (at least 2 s added; the clip plus the result stay within 30 s). The clip must be uploaded first with POST /v1/uploads (public URLs are not accepted). Billed on the clip's seconds plus the output's, in whole tokens. Required scope: videos:create.",
        "tags": [
          "Video"
        ],
        "x-required-scope": "videos:create",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VideoToolRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/CreateJobResult"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientBalance"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/audio": {
      "post": {
        "operationId": "postAudio",
        "summary": "Create an audio generation job: text-to-speech with model kreator-speech, or sound/music with model kreator-sound",
        "description": "Create an audio generation job: text-to-speech with model kreator-speech, or sound/music with model kreator-sound. Completes in one call; the returned job is already terminal. Required scope: audio:create.",
        "tags": [
          "Audio"
        ],
        "x-required-scope": "audio:create",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AudioRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/CreateJobResult"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientBalance"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/lip-sync": {
      "post": {
        "operationId": "postLipSync",
        "summary": "Create a Lip Sync job (OmniHuman 2.0): one photo plus one voice track becomes a video of that person speaking it",
        "description": "Create a Lip Sync job (OmniHuman 2.0): one photo plus one voice track becomes a video of that person speaking it. Paid accounts only. Priced per started second of audio. Returns a job to poll with GET /v1/jobs/{job_id}. Required scope: videos:create. Rate limit: 20 per 60 seconds per account.",
        "tags": [
          "Lip Sync"
        ],
        "x-required-scope": "videos:create",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LipSyncRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/CreateJobResult"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientBalance"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/voices": {
      "get": {
        "operationId": "getVoices",
        "summary": "List usable text-to-speech voice ids (preset catalogue plus the workspace's ready cloned voices)",
        "description": "List usable text-to-speech voice ids (preset catalogue plus the workspace's ready cloned voices). Required scope: models:read.",
        "tags": [
          "Audio"
        ],
        "x-required-scope": "models:read",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "$ref": "#/components/schemas/VoiceList"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/jobs/{job_id}": {
      "get": {
        "operationId": "getJobsByJobId",
        "summary": "Poll a job created by the same developer account",
        "description": "Poll a job created by the same developer account. Required scope: jobs:read. Rate limit: 120 per 60 seconds per account.",
        "tags": [
          "Jobs"
        ],
        "x-required-scope": "jobs:read",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "const": true
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "job"
                      ],
                      "properties": {
                        "job": {
                          "$ref": "#/components/schemas/Job"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/jobs/{job_id}/output": {
      "get": {
        "operationId": "getJobsByJobIdOutput",
        "summary": "Download a completed job's output (the providerOutputUrl) with your API key; supports HTTP range requests for video",
        "description": "Download a completed job's output (the providerOutputUrl) with your API key; supports HTTP range requests for video. Required scope: jobs:read. Rate limit: 300 per 60 seconds per account.",
        "tags": [
          "Jobs"
        ],
        "x-required-scope": "jobs:read",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The finished file (video, image or audio). Supports HTTP range requests for video.",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "head": {
        "operationId": "headJobsByJobIdOutputHead",
        "summary": "Download a completed job's output (the providerOutputUrl) with your API key; supports HTTP range requests for video",
        "description": "Download a completed job's output (the providerOutputUrl) with your API key; supports HTTP range requests for video. Required scope: jobs:read. Rate limit: 300 per 60 seconds per account.",
        "tags": [
          "Jobs"
        ],
        "x-required-scope": "jobs:read",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Headers of the finished file (size, type, range support)."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/v1/mcp": {
      "post": {
        "operationId": "postMcp",
        "summary": "Developer MCP server (Streamable HTTP, JSON-RPC)",
        "description": "Model Context Protocol endpoint for AI assistants and agents. Send JSON-RPC 2.0 messages (initialize, tools/list, tools/call) with your API key as the bearer token. Tools call the same /v1 service, so jobs are quoted, reserved and billed exactly like the HTTP API. Stateless: GET returns 405. An unauthenticated request gets 401 with a WWW-Authenticate: Bearer challenge.",
        "tags": [
          "MCP"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "A JSON-RPC 2.0 request or batch.",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC 2.0 response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    }
  },
  "webhooks": {
    "jobEvent": {
      "post": {
        "operationId": "jobEventWebhook",
        "summary": "Job finished",
        "description": "Sent to the webhook_url of a job when it ends (job.completed, job.failed, job.canceled, job.blocked). Headers: X-KreatorFlow-Event-Id, X-KreatorFlow-Event-Type, X-KreatorFlow-Job-Id, X-KreatorFlow-Timestamp, X-KreatorFlow-Signature. X-KreatorFlow-Signature is t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\"> with your workspace signing secret (Webhooks tab in the console); reject events older than 5 minutes and use the event id to skip duplicates. Each event is attempted up to 3 times; answer 2xx quickly.",
        "parameters": [
          {
            "name": "X-KreatorFlow-Event-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-KreatorFlow-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-KreatorFlow-Job-Id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-KreatorFlow-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-KreatorFlow-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "object",
                  "id",
                  "type",
                  "created",
                  "data"
                ],
                "properties": {
                  "object": {
                    "type": "string",
                    "const": "kreatorflow.developer_webhook_event"
                  },
                  "id": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "job.completed",
                      "job.failed",
                      "job.canceled",
                      "job.blocked"
                    ]
                  },
                  "created": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "job": {
                        "$ref": "#/components/schemas/Job"
                      }
                    }
                  }
                }
              },
              "example": {
                "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"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx acknowledges the event."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Your KreatorFlow API key (kf_...) as a bearer token. Keep it on your server."
      },
      "apiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Alternative to the Authorization header."
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "maxLength": 160
        },
        "description": "Send the same key when retrying a create and you get the original job back instead of a second one. Up to 160 characters (a UUID is ideal). Keys belong to the account (not one API key or endpoint), do not expire, and are matched on the key alone: a reused key returns the original job even if the request differs."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid request. reference_upload_not_developer: The upload_id is a file uploaded on the website, not through the API. prompt_required: No prompt (or text for speech) was sent. prompt_too_long: The prompt is over the model's limit. model_not_found: Unknown model alias. duration_not_supported: The model doesn't offer that length. aspect_ratio_not_supported: The model doesn't offer that aspect ratio. resolution_not_supported: The model doesn't offer that resolution. reference_combination_not_supported: These references can't be combined, e.g. start/end frames with reference images. upload_invalid: The upload request is missing a field or has a bad type. video_edit_model_not_supported: Video edits need a Seedance 2.0 family model (2.0, Fast or Mini). video_edit_source_required: A video edit needs a source clip. voice_required: Speech needs a voice. audio_reference_too_long: The audio references add up to more than the model accepts in total (15 s on Seedance 2.0, 30 s on 2.5). Nothing was charged. audio_too_short: The voice track is under 4 seconds. Nothing was charged. audio_too_long: The voice track is over 5 minutes. Nothing was charged. audio_unreadable: The audio couldn't be read. Nothing was charged.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, wrong or revoked API key. invalid_api_key: The key is missing, wrong or revoked.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "headers": {
          "WWW-Authenticate": {
            "schema": {
              "type": "string"
            },
            "description": "Bearer challenge (on /v1/mcp)."
          }
        }
      },
      "Forbidden": {
        "description": "Not allowed. account_not_active: The developer account is suspended. scope_missing: The key lacks the scope this endpoint needs. paid_account_required: Lip Sync needs a paid account. Nothing was charged.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "InsufficientBalance": {
        "description": "Not enough tokens for the quoted cost; top up and retry. insufficient_balance: Not enough tokens for the quoted cost.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Not found. job_not_found: No job with that id for this key's account. character_not_found: The character id or slug doesn't exist. upload_not_found: The upload_id doesn't exist in this workspace. reference_upload_not_found: A reference upload_id doesn't exist in this workspace. video_edit_source_not_found: The source_video_upload_id doesn't exist. image_upload_not_found: The image_upload_id isn't in this workspace. audio_upload_not_found: The audio_upload_id isn't in this workspace (or audio_job_id isn't a completed /v1/audio job).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests in the window.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        },
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds to wait."
          }
        }
      }
    },
    "schemas": {
      "UploadCreateRequest": {
        "type": "object",
        "properties": {
          "file_name": {
            "type": "string",
            "description": "string required; camelCase fileName also accepted"
          },
          "mime_type": {
            "type": "string",
            "description": "string required; camelCase mimeType also accepted"
          },
          "file_size": {
            "type": "number",
            "description": "number required; camelCase fileSize also accepted"
          },
          "upload_type": {
            "type": "string",
            "description": "IMAGE, VIDEO, OTHER, or AUDIO; camelCase uploadType also accepted"
          }
        },
        "required": [
          "file_name",
          "mime_type",
          "file_size"
        ],
        "additionalProperties": true
      },
      "UploadCreateResponse": {
        "type": "object",
        "properties": {
          "upload_id": {
            "type": "string",
            "description": "workspace-scoped upload id; use this in generation references"
          },
          "direct_upload_url": {
            "type": "string",
            "description": "RECOMMENDED. Absolute presigned TOS URL, PUT the raw bytes straight here (bypasses the ~4.5MB proxy cap, up to the documented media limits). Send EXACTLY the direct_upload_headers."
          },
          "direct_upload_headers": {
            "type": "object",
            "additionalProperties": true,
            "description": "object of headers that MUST be sent verbatim on the direct_upload_url PUT (Content-Type is signed; a mismatch is rejected by storage)"
          },
          "direct_upload_expires_at": {
            "type": "string",
            "description": "direct_upload_url expiry (~10 min); request a new upload if it lapses"
          },
          "complete_url": {
            "type": "string",
            "description": "absolute URL, POST here after the direct_upload_url PUT to finalize and make the upload usable (returns the ready upload_id)"
          },
          "upload_url": {
            "type": "string",
            "description": "absolute fallback PUT URL for SMALL files only (<~4.5MB), the proxy path; large files MUST use direct_upload_url"
          },
          "upload_method": {
            "type": "string",
            "description": "PUT"
          },
          "upload_mode": {
            "type": "string",
            "description": "direct"
          },
          "expires_at": {
            "type": "string",
            "description": "upload reservation expiry timestamp"
          }
        },
        "additionalProperties": true
      },
      "UploadCompleteResponse": {
        "type": "object",
        "properties": {
          "upload_id": {
            "type": "string",
            "description": "the now-ready workspace-scoped upload_id; uploadId is also returned"
          },
          "status": {
            "type": "string",
            "description": "\"ready\" once the stored bytes are verified and the upload is usable"
          },
          "file_size": {
            "type": "string",
            "description": "verified stored file size in bytes"
          },
          "mime_type": {
            "type": "string",
            "description": "verified stored MIME type (the sniffed content type)"
          }
        },
        "additionalProperties": true
      },
      "ImageRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "description": "string optional, defaults to kreator-image-pro"
          },
          "prompt": {
            "type": "string",
            "description": "string required"
          },
          "response_format": {
            "type": "string",
            "description": "url optional; defaults to url"
          },
          "watermark": {
            "type": "boolean",
            "description": "boolean optional, defaults to false"
          },
          "seed": {
            "type": "integer",
            "description": "integer optional"
          },
          "aspect_ratio": {
            "type": "string",
            "description": "string optional"
          },
          "ratio": {
            "type": "string",
            "description": "alias for aspect_ratio"
          },
          "resolution": {
            "type": "string",
            "description": "string optional"
          },
          "references": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Reference"
            },
            "description": "array optional; supports url or upload_id"
          },
          "reference_upload_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; image upload_id values"
          },
          "reference_image_upload_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; image upload_id values"
          },
          "character_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; reusable character ids/slugs from POST /v1/characters mode=register"
          },
          "safety_identifier": {
            "type": "string",
            "description": "string optional, max 64 chars"
          },
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "description": "https url optional; receives terminal job callbacks"
          },
          "callback_url": {
            "type": "string",
            "description": "alias for webhook_url"
          },
          "idempotency_key": {
            "type": "string",
            "description": "string optional body fallback; prefer Idempotency-Key header"
          }
        },
        "required": [
          "prompt"
        ],
        "additionalProperties": true
      },
      "CharacterRequest": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "description": "register/save/asset to save a reusable character; omit for prompt-mode generation"
          },
          "name": {
            "type": "string",
            "description": "string optional developer-facing label"
          },
          "upload_id": {
            "type": "string",
            "description": "string required for register mode; owned image upload_id from POST /v1/uploads"
          },
          "prompt": {
            "type": "string",
            "description": "string required for prompt-mode generation; describe character appearance, wardrobe, pose, style, and composition"
          },
          "description": {
            "type": "string",
            "description": "string optional alias/fallback for prompt"
          },
          "model": {
            "type": "string",
            "description": "string optional image alias, defaults to kreator-image-pro"
          },
          "aspect_ratio": {
            "type": "string",
            "description": "string optional"
          },
          "ratio": {
            "type": "string",
            "description": "alias for aspect_ratio"
          },
          "resolution": {
            "type": "string",
            "description": "string optional"
          },
          "reference_upload_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array required for prompt-mode generation when character_ids is omitted; owned image upload_id values from POST /v1/uploads; use readable images at least 300px wide"
          },
          "reference_image_upload_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional alias; owned image upload_id values"
          },
          "character_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; reusable character ids/slugs from POST /v1/characters mode=register"
          },
          "safety_identifier": {
            "type": "string",
            "description": "string optional, max 64 chars"
          },
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "description": "https url optional; receives terminal job callbacks"
          },
          "callback_url": {
            "type": "string",
            "description": "alias for webhook_url"
          },
          "idempotency_key": {
            "type": "string",
            "description": "string optional body fallback; prefer Idempotency-Key header"
          }
        },
        "additionalProperties": true
      },
      "Character": {
        "type": "object",
        "properties": {
          "character_id": {
            "type": "string",
            "description": "reusable character id; id is also returned with the same value"
          },
          "slug": {
            "type": "string",
            "description": "workspace-unique character slug"
          },
          "variable_ref": {
            "type": "string",
            "description": "variable reference token for the character slug, for use in prompts"
          },
          "upload_id": {
            "type": "string",
            "description": "the owned image upload_id the character was registered from, or null"
          },
          "status": {
            "type": "string",
            "description": "\"ready\", \"pending\", or \"failed\" (reusable asset provisioning state)"
          },
          "name": {
            "type": "string",
            "description": "developer-facing character label or null"
          },
          "prompt": {
            "type": "string",
            "description": "stored appearance note or null"
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 timestamp"
          },
          "updated_at": {
            "type": "string",
            "description": "ISO 8601 timestamp"
          }
        },
        "additionalProperties": true
      },
      "VideoRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "description": "string optional, defaults to kreator-video-fast; defaults to kreator-video-pro when intent=video_edit"
          },
          "intent": {
            "type": "string",
            "description": "string optional; set to video_edit for source-video edit mode on /v1/videos"
          },
          "edit_mode": {
            "type": "string",
            "description": "transform, restyle, or extend when intent=video_edit; editMode alias accepted"
          },
          "source_video_upload_id": {
            "type": "string",
            "description": "preferred owned same-workspace VIDEO upload_id for source-video edit mode; create it with upload_type VIDEO; MP4/MOV with H.264 or H.265, up to 200 MB, recommended; sourceVideoUploadId alias accepted"
          },
          "video": {
            "type": "string",
            "description": "public HTTPS source video URL alias for source-video edit mode; source_video_url/sourceVideoUrl also accepted"
          },
          "source_video_url": {
            "type": "string",
            "description": "public HTTPS source video URL alias for source-video edit mode"
          },
          "source_model_key": {
            "type": "string",
            "description": "optional compatibility hint for previous Seedance 2 sources; omit for newly uploaded source clips"
          },
          "prompt": {
            "type": "string",
            "description": "string required unless content includes a text item"
          },
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContentItem"
            },
            "description": "KreatorFlow content array optional"
          },
          "duration": {
            "type": "number",
            "description": "number optional, rounded up and validated against model limits"
          },
          "aspect_ratio": {
            "type": "string",
            "description": "string optional; source-video edit defaults to adaptive when omitted"
          },
          "ratio": {
            "type": "string",
            "description": "alias for aspect_ratio; source-video edit accepts adaptive"
          },
          "resolution": {
            "type": "string",
            "description": "string optional"
          },
          "generate_audio": {
            "type": "boolean",
            "description": "boolean optional"
          },
          "watermark": {
            "type": "boolean",
            "description": "boolean optional, defaults to false"
          },
          "seed": {
            "type": "integer",
            "description": "integer optional"
          },
          "camera_fixed": {
            "type": "boolean",
            "description": "boolean optional"
          },
          "references": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Reference"
            },
            "description": "array optional; supports url or upload_id"
          },
          "first_frame_upload_id": {
            "type": "string",
            "description": "image upload_id for the first frame; firstFrameUploadId and first_frame_image_upload_id aliases accepted"
          },
          "last_frame_upload_id": {
            "type": "string",
            "description": "image upload_id for the last frame; lastFrameUploadId and last_frame_image_upload_id aliases accepted"
          },
          "first_frame_url": {
            "type": "string",
            "description": "public HTTPS image URL for the first frame; firstFrameUrl and first_frame_image_url aliases accepted"
          },
          "last_frame_url": {
            "type": "string",
            "description": "public HTTPS image URL for the last frame; lastFrameUrl and last_frame_image_url aliases accepted"
          },
          "reference_upload_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; image upload_id values"
          },
          "reference_image_upload_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; image upload_id values"
          },
          "reference_image_urls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; public HTTPS image URLs; reference_images/referenceImages also accepted"
          },
          "reference_video_upload_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; video upload_id values for normal generation clip guidance; source-video edit should use source_video_upload_id"
          },
          "reference_video_urls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; public HTTPS video URLs for normal generation clip guidance; reference_videos/referenceVideos also accepted"
          },
          "reference_audio_upload_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; audio upload_id values"
          },
          "reference_audio_urls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; public HTTPS audio URLs; reference_audios/referenceAudios also accepted"
          },
          "character_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; reusable character ids/slugs from POST /v1/characters mode=register"
          },
          "video_role": {
            "type": "string",
            "description": "string optional, reference (default) or edit, on models whose notes list reference clips: reference uses the clips for style, motion or subject; edit changes the one clip by the prompt and keeps its length and shape"
          },
          "keep_clip_sound": {
            "type": "boolean",
            "description": "boolean optional, defaults to true; with video_role edit, keeps the clip's own sound on models that can drop it"
          },
          "shots": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "duration",
                "prompt"
              ],
              "properties": {
                "duration": {
                  "type": "integer"
                },
                "prompt": {
                  "type": "string"
                }
              }
            },
            "description": "array optional of { duration, prompt } objects, on models whose notes list a shot list: 2 to 6 shots whose durations add up to duration; prompt then becomes an optional lead-in"
          },
          "voice_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; cloned voice ids from GET /v1/voices (cloned:<id>), on models whose notes list voices of their own, named @voice_1.. in the prompt"
          },
          "character_voices": {
            "type": "object",
            "additionalProperties": true,
            "description": "object optional, { character_id: voice id }, on models whose notes list cloned voices: the character (also in character_ids) speaks with that cloned voice"
          },
          "face_consent": {
            "type": "boolean",
            "description": "boolean optional; when a reference video is combined with image references (a face onto a person), true records your confirmation that you are the person in the image or have their permission (otherwise your acceptance of the Terms and Acceptable Use Policy is recorded); same rules as on POST /v1/video-edits, including uploaded images only (image upload_id, not a public link)"
          },
          "video_reference_mode": {
            "type": "string",
            "description": "fallback or strict optional; defaults to fallback for normal generation; source-video edit forces strict"
          },
          "safety_identifier": {
            "type": "string",
            "description": "string optional, max 64 chars"
          },
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "description": "https url optional; receives terminal job callbacks"
          },
          "callback_url": {
            "type": "string",
            "description": "alias for webhook_url"
          },
          "idempotency_key": {
            "type": "string",
            "description": "string optional body fallback; prefer Idempotency-Key header"
          }
        },
        "additionalProperties": true
      },
      "VideoEditRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "description": "string optional, defaults to kreator-video-pro; must be a Seedance 2 video alias"
          },
          "edit_mode": {
            "type": "string",
            "description": "required transform, restyle, or extend; editMode alias accepted"
          },
          "source_video_upload_id": {
            "type": "string",
            "description": "preferred owned same-workspace VIDEO upload_id from POST /v1/uploads with upload_type VIDEO; image/audio upload ids are rejected before billing; MP4/MOV with H.264 or H.265, up to 200 MB, recommended; sourceVideoUploadId alias accepted"
          },
          "video": {
            "type": "string",
            "description": "public HTTPS source video URL alias; source_video_url/sourceVideoUrl also accepted and normalized through KreatorFlow video storage"
          },
          "source_video_url": {
            "type": "string",
            "description": "public HTTPS source video URL alias for source-video edit mode"
          },
          "source_model_key": {
            "type": "string",
            "description": "optional compatibility hint for previous Seedance 2 sources; omit for newly uploaded source clips"
          },
          "prompt": {
            "type": "string",
            "description": "string required edit instruction for transform/restyle; optional for extend (a default continuation is used)"
          },
          "face_consent": {
            "type": "boolean",
            "description": "boolean optional; when image references are sent with the source video (a face onto a person), true records your confirmation that you are the person in the image or have their permission (otherwise your acceptance of the Terms and Acceptable Use Policy is recorded). Recorded with the job. Face edits also need a paid account, take uploaded images only (image upload_id from POST /v1/uploads; public image links are refused with face_image_upload_required) and pass a nudity/minor check on the images before anything is charged"
          },
          "duration": {
            "type": "number",
            "description": "number optional, rounded up and validated against model limits"
          },
          "aspect_ratio": {
            "type": "string",
            "description": "string optional; defaults to adaptive to preserve source-video framing"
          },
          "ratio": {
            "type": "string",
            "description": "alias for aspect_ratio; adaptive preserves source-video framing"
          },
          "resolution": {
            "type": "string",
            "description": "string optional"
          },
          "generate_audio": {
            "type": "boolean",
            "description": "boolean optional"
          },
          "character_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; reusable character ids/slugs from POST /v1/characters mode=register; used as owned/authorized appearance guidance on source-video edits; celebrity, public-figure, deepfake, and impersonation wording is rejected"
          },
          "reference_upload_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; extra image upload_id values for authorized appearance, style, wardrobe, product, or composition guidance"
          },
          "reference_image_upload_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; extra image upload_id values for authorized appearance, style, wardrobe, product, or composition guidance"
          },
          "reference_image_urls": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; extra public HTTPS image URLs for authorized appearance, style, wardrobe, product, or composition guidance; reference_images/referenceImages also accepted. Not accepted for face edits (image references with a source video): use reference_image_upload_ids"
          },
          "reference_video_upload_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; extra clip guidance; source_video_upload_id or video/source_video_url is always strict and required"
          },
          "reference_audios": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; public HTTPS audio reference URLs; equivalent to reference_audio_urls"
          },
          "safety_identifier": {
            "type": "string",
            "description": "string optional, max 64 chars"
          },
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "description": "https url optional; receives terminal job callbacks"
          },
          "callback_url": {
            "type": "string",
            "description": "alias for webhook_url"
          },
          "idempotency_key": {
            "type": "string",
            "description": "string optional body fallback; prefer Idempotency-Key header"
          }
        },
        "required": [
          "edit_mode"
        ],
        "additionalProperties": true
      },
      "VideoToolRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "description": "string optional; kreator-video-wan-3-prime or kreator-video-wan-3 (when enabled for your account)"
          },
          "source": {
            "type": "string",
            "description": "required; the clip: an upload_id from POST /v1/uploads (upload_type VIDEO), asset:<id>, generation:<id>, a kreatorflow.ai media link or an @handle. Public URLs are not accepted: upload the clip with POST /v1/uploads first. video / source_video / video_upload_id also accepted. MP4 or MOV, up to 15 s"
          },
          "instruction": {
            "type": "string",
            "description": "edit: required, what to change (up to 1500 characters); extend: optional, what happens in the new part. prompt / text also accepted. Name references as Image 1, Video 2, Audio 1 or by @handle"
          },
          "references": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Reference"
            },
            "description": "array optional; extra images, clips or audio in the same forms as source (uploaded with POST /v1/uploads, not public URLs), in prompt order after the clip"
          },
          "direction": {
            "type": "string",
            "description": "extend only: after (default), before or both"
          },
          "add_seconds": {
            "type": "string",
            "description": "extend only: seconds to add, at least 2; the clip plus the result stay within 30 s"
          },
          "resolution": {
            "type": "string",
            "description": "720p (default) or 1080p; anything else is refused with 400 resolution_not_supported before anything is reserved"
          },
          "aspect_ratio": {
            "type": "string",
            "description": "optional; 16:9, 9:16, 1:1, 4:3, 3:4 or 21:9 (default: keep the clip's shape); anything else is refused with 400 aspect_ratio_not_supported"
          },
          "seed": {
            "type": "integer",
            "description": "integer optional"
          },
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "description": "https url optional; receives terminal job callbacks"
          },
          "idempotency_key": {
            "type": "string",
            "description": "string optional body fallback; prefer Idempotency-Key header"
          }
        },
        "required": [
          "source"
        ],
        "additionalProperties": true
      },
      "AudioRequest": {
        "type": "object",
        "properties": {
          "model": {
            "type": "string",
            "description": "string optional; kreator-speech (text-to-speech, default) or kreator-sound (sound/music)"
          },
          "text": {
            "type": "string",
            "description": "string required for kreator-speech; the words to speak (prompt alias also accepted)"
          },
          "prompt": {
            "type": "string",
            "description": "string required for kreator-sound; describes the sound/music (text alias also accepted)"
          },
          "voice": {
            "type": "string",
            "description": "string required for kreator-speech; a voice id from GET /v1/voices (voice_id/voiceType aliases accepted)"
          },
          "format": {
            "type": "string",
            "description": "string optional; mp3 or wav (provider decides the delivered container; best-effort)"
          },
          "speed": {
            "type": "number",
            "description": "number optional delivery ratio (~0.5-2.0, 1.0 = neutral)"
          },
          "volume": {
            "type": "number",
            "description": "number optional delivery ratio (~0.5-2.0, 1.0 = neutral)"
          },
          "pitch": {
            "type": "number",
            "description": "number optional delivery ratio (~0.5-2.0, 1.0 = neutral); tone alias accepted"
          },
          "emotion": {
            "type": "string",
            "description": "string optional (kreator-speech); applied when the voice supports it"
          },
          "emotion_scale": {
            "type": "number",
            "description": "number optional 1-5 (kreator-speech); emotionScale alias accepted"
          },
          "safety_identifier": {
            "type": "string",
            "description": "string optional, max 64 chars"
          },
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "description": "https url optional; receives terminal job callbacks"
          },
          "callback_url": {
            "type": "string",
            "description": "alias for webhook_url"
          },
          "idempotency_key": {
            "type": "string",
            "description": "string optional body fallback; prefer Idempotency-Key header"
          }
        },
        "additionalProperties": true
      },
      "LipSyncRequest": {
        "type": "object",
        "properties": {
          "image_upload_id": {
            "type": "string",
            "description": "string required; the photo of the person who speaks: an IMAGE upload_id from POST /v1/uploads (one clearly visible face works best); imageUploadId also accepted"
          },
          "audio_upload_id": {
            "type": "string",
            "description": "string required unless audio_job_id is sent; the voice track: an audio upload_id from POST /v1/uploads (MP3 or WAV, 4 seconds to 5 minutes, 15 MB max); audioUploadId also accepted"
          },
          "audio_job_id": {
            "type": "string",
            "description": "string required unless audio_upload_id is sent; the id of a completed POST /v1/audio job of the same account, used as the voice track; audioJobId also accepted"
          },
          "face_consent": {
            "type": "boolean",
            "description": "boolean optional: true records your own confirmation that you are the person in the photo or have their permission. Your acceptance of the Terms and Acceptable Use Policy covers it either way. Recorded with the job"
          },
          "prompt": {
            "type": "string",
            "description": "string optional, max 2000 chars; direction for expression, gestures or camera"
          },
          "resolution": {
            "type": "string",
            "description": "string optional; 720p (default) or 1080p"
          },
          "webhook_url": {
            "type": "string",
            "format": "uri",
            "description": "https url optional; receives terminal job callbacks"
          },
          "callback_url": {
            "type": "string",
            "description": "alias for webhook_url"
          },
          "idempotency_key": {
            "type": "string",
            "description": "string optional body fallback; prefer Idempotency-Key header"
          }
        },
        "required": [
          "image_upload_id"
        ],
        "additionalProperties": true
      },
      "ModelList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "description": "\"list\""
          },
          "models": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array of model-alias objects (id, name, cleanModelName, mediaType, tier, status, maxPromptChars, limits, strengths)"
          },
          "actual_models": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array of clean-model objects (name, mediaType, status, exposedAliasIds, notes)"
          }
        },
        "additionalProperties": true
      },
      "VoiceList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "description": "list"
          },
          "voices": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array of usable text-to-speech voices; each has id (use as `voice` on /v1/audio), name, language, kind (kreatorflow/preset/cloned) and optional emotions; the underlying provider voice id is never exposed"
          }
        },
        "additionalProperties": true
      },
      "Job": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "string"
          },
          "mediaType": {
            "type": "string",
            "description": "image, video, or audio"
          },
          "modelId": {
            "type": "string",
            "description": "stable KreatorFlow model alias"
          },
          "status": {
            "type": "string",
            "description": "created, queued, processing, completed, failed, canceled, or blocked",
            "enum": [
              "created",
              "queued",
              "processing",
              "completed",
              "failed",
              "canceled",
              "blocked"
            ]
          },
          "provider": {
            "type": "string",
            "description": "KreatorFlow routing label or null; upstream routing names are not exposed"
          },
          "providerJobId": {
            "type": "string",
            "description": "always null in public API responses; poll by the KreatorFlow job id"
          },
          "providerOutputId": {
            "type": "string",
            "description": "always null in public API responses"
          },
          "providerOutputUrl": {
            "type": "string",
            "description": "KreatorFlow-authenticated output URL or null; fetch with your API key and store the output in your own storage"
          },
          "providerOutputExpiresAt": {
            "type": "string",
            "description": "usually null; providerOutputUrl is a stable KreatorFlow URL that does not expire (it is served while the output is retained)"
          },
          "prompt": {
            "type": "string",
            "description": "string the job's prompt"
          },
          "quotedTokenCost": {
            "type": "number",
            "description": "number token quote at create (for video with input, the maximum)"
          },
          "estimatedTokenCost": {
            "type": "number",
            "description": "number alias of quotedTokenCost"
          },
          "reservedTokenCost": {
            "type": "number",
            "description": "number tokens held for the job while it runs"
          },
          "finalTokenCost": {
            "type": "number",
            "description": "number tokens actually charged; 0 until the job completes, and 0 for failed or canceled jobs"
          },
          "referenceDropped": {
            "type": "boolean",
            "description": "boolean optional; true when a fallback output omitted video clip references"
          },
          "errorData": {
            "type": "object",
            "additionalProperties": true,
            "description": "object optional; details for reference asset errors"
          },
          "createdAt": {
            "type": "string",
            "description": "string ISO timestamp"
          },
          "updatedAt": {
            "type": "string",
            "description": "string ISO timestamp"
          },
          "completedAt": {
            "type": "string",
            "description": "string ISO timestamp or null"
          },
          "errorCode": {
            "type": "string",
            "description": "string or null"
          },
          "errorMessage": {
            "type": "string",
            "description": "string or null"
          },
          "resolution": {
            "type": "string",
            "description": "string optional; video jobs: the requested output resolution"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "array optional; includes video_reference_fallback_omitted_clips when a fallback output omitted video clip references"
          }
        },
        "additionalProperties": true
      },
      "CreateJobResult": {
        "type": "object",
        "properties": {
          "job": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Job"
              },
              {
                "type": "null"
              }
            ],
            "description": "object the accepted Job (same shape as GET /v1/jobs/{id}); null on a 402 when another request used the balance first. Image/character dispatch can continue asynchronously, while video create attempts KreatorFlow dispatch before returning"
          },
          "balance_tokens": {
            "type": "number",
            "description": "number current developer token balance after reservation or replay"
          },
          "quoted_token_cost": {
            "type": "number",
            "description": "number token quote for the submitted request"
          },
          "quoted_token_cost_is_maximum": {
            "type": "boolean",
            "description": "boolean optional; true when the job has video input: the quote is a ceiling and the final charge (on the measured input) is never higher. Only in the create response, so store it"
          },
          "video_input_max_seconds": {
            "type": "number",
            "description": "number optional; with quoted_token_cost_is_maximum, the input length the quote assumed"
          },
          "estimated_token_cost": {
            "type": "number",
            "description": "number compatibility alias for quoted_token_cost"
          },
          "idempotent_replay": {
            "type": "boolean",
            "description": "boolean optional; true when the same Idempotency-Key returned an existing job instead of creating or dispatching another one"
          }
        },
        "additionalProperties": true
      },
      "Reference": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "image_url",
              "video_url",
              "audio_url"
            ]
          },
          "url": {
            "type": "string",
            "description": "public https url"
          },
          "upload_id": {
            "type": "string",
            "description": "workspace-scoped upload_id returned by POST /v1/uploads"
          },
          "role": {
            "type": "string",
            "description": "optional content role such as first_frame, last_frame, reference_image, reference_video, reference_audio"
          }
        },
        "additionalProperties": true
      },
      "ContentItem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "text",
              "image_url",
              "video_url",
              "audio_url"
            ]
          },
          "text": {
            "type": "string",
            "description": "string when type=text"
          },
          "image_url": {
            "type": "string",
            "format": "uri",
            "description": "https url string or object with url or upload_id when type=image_url"
          },
          "video_url": {
            "type": "string",
            "format": "uri",
            "description": "https url string or object with url or upload_id when type=video_url"
          },
          "audio_url": {
            "type": "string",
            "format": "uri",
            "description": "https url string or object with url or upload_id when type=audio_url"
          },
          "role": {
            "type": "string",
            "description": "optional role for reference content"
          }
        },
        "additionalProperties": true
      },
      "Error": {
        "type": "object",
        "required": [
          "success",
          "code",
          "error"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "const": false
          },
          "code": {
            "type": "string",
            "description": "Machine-readable error code.",
            "enum": [
              "account_not_active",
              "aspect_ratio_not_supported",
              "audio_reference_too_long",
              "audio_too_long",
              "audio_too_short",
              "audio_unreadable",
              "audio_upload_not_found",
              "character_not_found",
              "character_pending",
              "character_reference_limit_exceeded",
              "character_reference_unusable",
              "character_reference_upload_required",
              "character_registration_failed",
              "character_trusted_asset_failed",
              "dispatch_disabled",
              "duration_not_supported",
              "face_image_upload_required",
              "generation_dispatch_failed",
              "generation_dispatch_missing",
              "generation_failed",
              "generation_output_missing",
              "generation_poll_failed",
              "generation_rejected",
              "generation_timeout",
              "generation_unavailable",
              "image_rejected",
              "image_upload_not_found",
              "insufficient_balance",
              "internal_error",
              "invalid_api_key",
              "job_not_found",
              "model_not_found",
              "paid_account_required",
              "paid_check_unavailable",
              "prompt_required",
              "prompt_too_long",
              "rate_limited",
              "reference_asset_failed",
              "reference_asset_pending",
              "reference_combination_not_supported",
              "reference_rejected",
              "reference_upload_invalid",
              "reference_upload_not_developer",
              "reference_upload_not_found",
              "reference_upload_unusable",
              "resolution_not_supported",
              "response_format_not_supported",
              "schema_missing",
              "scope_missing",
              "storage_not_configured",
              "upload_id_invalid",
              "upload_in_use",
              "upload_invalid",
              "upload_not_found",
              "upload_state_error",
              "upload_too_large",
              "video_edit_model_not_supported",
              "video_edit_source_must_be_video",
              "video_edit_source_not_found",
              "video_edit_source_required",
              "voice_not_found",
              "voice_required"
            ]
          },
          "error": {
            "type": "string",
            "description": "Human-readable message."
          }
        },
        "additionalProperties": true
      }
    },
    "x-scopes": {
      "models:read": "Scope models:read",
      "uploads:create": "Scope uploads:create",
      "images:create": "Scope images:create",
      "videos:create": "Scope videos:create",
      "audio:create": "Scope audio:create",
      "jobs:read": "Scope jobs:read"
    }
  },
  "x-job-error-codes": [
    {
      "code": "reference_rejected",
      "meaning": "A reference did not pass screening."
    },
    {
      "code": "reference_asset_pending",
      "meaning": "A new reference is still being reviewed."
    },
    {
      "code": "reference_asset_failed",
      "meaning": "The reference did not pass review."
    },
    {
      "code": "generation_rejected",
      "meaning": "The request was declined (prompt, reference or options)."
    },
    {
      "code": "generation_timeout",
      "meaning": "The job ran out of time after automatic retries."
    },
    {
      "code": "generation_unavailable",
      "meaning": "The model is temporarily unavailable."
    },
    {
      "code": "generation_failed",
      "meaning": "The generation failed."
    }
  ]
}