{
  "openapi": "3.1.0",
  "info": {
    "title": "Dawnwood Models API",
    "version": "0.1.0",
    "summary": "Seedance video generation, billed per output second.",
    "description": "Seedance 2.0 Fast, 2.0 Mini, 2.0 and 2.5 over an HTTP API whose request body and task object follow BytePlus ModelArk's content-generation task format. Only successful generations are charged; the API spends purchased credits only. Prices: https://dawnwood.ai/models/ . This is separate from the Dawnwood pipeline API (console.dawnwood.ai/api, https://dawnwood.ai/llms.txt).",
    "contact": {
      "name": "Dawnwood support",
      "email": "support@dawnwood.ai",
      "url": "https://dawnwood.ai/models/"
    },
    "termsOfService": "https://dawnwood.ai/legal/terms/"
  },
  "servers": [
    {
      "url": "https://models.dawnwood.ai"
    }
  ],
  "externalDocs": {
    "url": "https://dawnwood.ai/docs/dawnwood-models-api/"
  },
  "paths": {
    "/v1/video/generations": {
      "post": {
        "summary": "Create a video generation task",
        "description": "Reserves credits for the requested duration. Credits are returned in full if the task fails.",
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Resubmitting with the same key returns the same task and is not charged again.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateGenerationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Task created. The body is the new task object; ModelArk-style clients only need its id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameter (`InvalidParameter`) or unsupported content (`unsupported_content`, e.g. `video_url`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, expired or revoked token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Token lacks the `model_api` scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Not enough purchased credits (`paid_credits_required`). Gift and subscription-included credits cannot be spent on the API.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key concurrency limit reached (`concurrency_limit`), or the request would go over a spend limit you set in the console (`spend_limit_reached`, with `scope` day/month/key and `limit_usd`; Retry-After = seconds until that limit resets).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before resubmitting.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "502": {
            "description": "The upstream model returned an error at submission (`upstream_error`). Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Model access is not open for this account yet (`models_not_open`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "operationId": "createVideoGeneration"
      }
    },
    "/v1/video/generations/{id}": {
      "get": {
        "summary": "Get a video generation task",
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "cgt-dw-…"
          }
        ],
        "responses": {
          "200": {
            "description": "The task.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, expired or revoked token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Token lacks the `model_api` scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No task with this id for this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "operationId": "getVideoGeneration"
      }
    },
    "/v1/contents/generations/tasks": {
      "post": {
        "summary": "Create a video generation task",
        "description": "Reserves credits for the requested duration. Credits are returned in full if the task fails. ModelArk-compatible alias of /v1/video/generations.",
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Resubmitting with the same key returns the same task and is not charged again.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateGenerationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Task created. The body is the new task object; ModelArk-style clients only need its id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameter (`InvalidParameter`) or unsupported content (`unsupported_content`, e.g. `video_url`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, expired or revoked token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Token lacks the `model_api` scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Not enough purchased credits (`paid_credits_required`). Gift and subscription-included credits cannot be spent on the API.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key concurrency limit reached (`concurrency_limit`), or the request would go over a spend limit you set in the console (`spend_limit_reached`, with `scope` day/month/key and `limit_usd`; Retry-After = seconds until that limit resets).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before resubmitting.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "502": {
            "description": "The upstream model returned an error at submission (`upstream_error`). Nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Model access is not open for this account yet (`models_not_open`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "operationId": "createContentsGenerationTask"
      }
    },
    "/v1/contents/generations/tasks/{id}": {
      "get": {
        "summary": "Get a video generation task",
        "security": [
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "cgt-dw-…"
          }
        ],
        "responses": {
          "200": {
            "description": "The task.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, expired or revoked token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Token lacks the `model_api` scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No task with this id for this account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "operationId": "getContentsGenerationTask",
        "description": "ModelArk-compatible alias of /v1/video/generations/{id}."
      }
    },
    "/v1/models": {
      "get": {
        "summary": "List models and prices",
        "operationId": "listModels",
        "security": [],
        "responses": {
          "200": {
            "description": "Models and per-second prices.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Model"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/models/usage": {
      "get": {
        "summary": "Usage and spend for a date range",
        "operationId": "getUsage",
        "description": "Totals, a row per UTC day (days with no requests included), and breakdowns by model and by key. Spend counts every request that was not refunded. With format=csv, returns one row per request instead.",
        "parameters": [
          {
            "name": "start",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "First UTC day, inclusive. Default: 29 days before end."
          },
          {
            "name": "end",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Last UTC day, inclusive. Default: today. The range is limited to 92 days."
          },
          {
            "name": "key_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Only requests made with this API key (its token id)."
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage report (JSON), or per-request rows (text/csv) with format=csv.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Bad date or a range over 92 days.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "dw_pat_v1_…",
        "description": "A Dawnwood personal access token with the model_api scope (console → Developers)."
      }
    },
    "schemas": {
      "CreateGenerationRequest": {
        "type": "object",
        "required": [
          "model",
          "content"
        ],
        "properties": {
          "model": {
            "type": "string",
            "enum": [
              "seedance-2.0-fast",
              "seedance-2.0-mini",
              "seedance-2.0",
              "seedance-2.5"
            ],
            "description": "Official dreamina-seedance-… model ids are accepted as aliases and echoed back as the short id."
          },
          "content": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/ContentItem"
            },
            "description": "At most one text item. first_frame/last_frame images and reference_image items cannot be mixed in one task. Per-model limits: seedance-2.0-fast: 4–15 s, ≤9 images, ≤3 audios; seedance-2.0-mini: 4–15 s, ≤9 images, ≤3 audios; seedance-2.0: 4–15 s, ≤9 images, ≤3 audios; seedance-2.5: 4–30 s, ≤30 images, ≤10 audios. video_url is not supported (400 unsupported_content)."
          },
          "resolution": {
            "type": "string",
            "enum": [
              "480p",
              "720p"
            ],
            "default": "720p"
          },
          "ratio": {
            "type": "string",
            "enum": [
              "16:9",
              "9:16",
              "1:1",
              "4:3",
              "3:4",
              "21:9",
              "adaptive"
            ]
          },
          "duration": {
            "type": "integer",
            "minimum": 4,
            "maximum": 30,
            "description": "Whole seconds of output; billed on this value. seedance-2.0-fast: 4–15 s, ≤9 images, ≤3 audios; seedance-2.0-mini: 4–15 s, ≤9 images, ≤3 audios; seedance-2.0: 4–15 s, ≤9 images, ≤3 audios; seedance-2.5: 4–30 s, ≤30 images, ≤10 audios"
          },
          "generate_audio": {
            "type": "boolean",
            "default": true
          },
          "seed": {
            "type": "integer"
          }
        }
      },
      "ContentItem": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/TextContent"
          },
          {
            "$ref": "#/components/schemas/ImageContent"
          },
          {
            "$ref": "#/components/schemas/AudioContent"
          }
        ]
      },
      "TextContent": {
        "type": "object",
        "required": [
          "type",
          "text"
        ],
        "properties": {
          "type": {
            "const": "text"
          },
          "text": {
            "type": "string"
          }
        }
      },
      "ImageContent": {
        "type": "object",
        "required": [
          "type",
          "image_url"
        ],
        "description": "Up to 30 per request depending on model.",
        "properties": {
          "type": {
            "const": "image_url"
          },
          "image_url": {
            "type": "object",
            "required": [
              "url"
            ],
            "properties": {
              "url": {
                "type": "string",
                "format": "uri"
              }
            }
          },
          "role": {
            "type": "string",
            "enum": [
              "first_frame",
              "last_frame",
              "reference_image"
            ]
          }
        }
      },
      "AudioContent": {
        "type": "object",
        "required": [
          "type",
          "audio_url"
        ],
        "description": "Up to 10 per request depending on model.",
        "properties": {
          "type": {
            "const": "audio_url"
          },
          "audio_url": {
            "type": "object",
            "required": [
              "url"
            ],
            "properties": {
              "url": {
                "type": "string",
                "format": "uri"
              }
            }
          },
          "role": {
            "type": "string",
            "enum": [
              "reference_audio"
            ]
          }
        }
      },
      "Task": {
        "type": "object",
        "required": [
          "id",
          "model",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "model": {
            "type": "string",
            "enum": [
              "seedance-2.0-fast",
              "seedance-2.0-mini",
              "seedance-2.0",
              "seedance-2.5"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "succeeded",
              "failed",
              "cancelled"
            ]
          },
          "content": {
            "type": "object",
            "properties": {
              "video_url": {
                "type": "string",
                "format": "uri",
                "description": "Valid for 24 hours."
              }
            }
          },
          "usage": {
            "type": "object",
            "properties": {
              "completion_tokens": {
                "type": "integer"
              },
              "total_tokens": {
                "type": "integer"
              }
            }
          },
          "resolution": {
            "type": "string",
            "enum": [
              "480p",
              "720p"
            ]
          },
          "ratio": {
            "type": "string",
            "enum": [
              "16:9",
              "9:16",
              "1:1",
              "4:3",
              "3:4",
              "21:9",
              "adaptive"
            ]
          },
          "duration": {
            "type": "integer"
          },
          "created_at": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "updated_at": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "error": {
            "$ref": "#/components/schemas/ErrorBody"
          },
          "billing": {
            "type": "object",
            "properties": {
              "credits": {
                "type": "number",
                "description": "1 credit = $0.10."
              },
              "usd": {
                "type": "number"
              },
              "refunded": {
                "type": "boolean",
                "description": "True when the reserved credits were returned (failed task)."
              }
            }
          }
        }
      },
      "Model": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              "seedance-2.0-fast",
              "seedance-2.0-mini",
              "seedance-2.0",
              "seedance-2.5"
            ]
          },
          "object": {
            "const": "model"
          },
          "owned_by": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "duration_range": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "minItems": 2,
            "maxItems": 2
          },
          "resolutions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "ratios": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "price_per_second_usd": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            }
          },
          "price_per_second_credits": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            }
          },
          "max_reference_images": {
            "type": "integer"
          },
          "max_reference_audios": {
            "type": "integer"
          },
          "reference_video": {
            "type": "boolean"
          }
        }
      },
      "ErrorBody": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "UsageBucket": {
        "type": "object",
        "properties": {
          "requests": {
            "type": "integer"
          },
          "succeeded": {
            "type": "integer"
          },
          "failed": {
            "type": "integer"
          },
          "in_progress": {
            "type": "integer"
          },
          "billed_seconds": {
            "type": "integer",
            "description": "Seconds of output billed (refunded requests excluded)."
          },
          "credits": {
            "type": "number"
          },
          "usd": {
            "type": "number"
          }
        }
      },
      "Usage": {
        "type": "object",
        "properties": {
          "object": {
            "const": "usage"
          },
          "start": {
            "type": "string",
            "format": "date"
          },
          "end": {
            "type": "string",
            "format": "date"
          },
          "timezone": {
            "const": "UTC"
          },
          "token_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "totals": {
            "$ref": "#/components/schemas/UsageBucket"
          },
          "daily": {
            "type": "array",
            "items": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/UsageBucket"
                },
                {
                  "type": "object",
                  "properties": {
                    "date": {
                      "type": "string",
                      "format": "date"
                    }
                  }
                }
              ]
            }
          },
          "by_model": {
            "type": "array",
            "items": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/UsageBucket"
                },
                {
                  "type": "object",
                  "properties": {
                    "model": {
                      "type": "string"
                    }
                  }
                }
              ]
            }
          },
          "by_key": {
            "type": "array",
            "items": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/UsageBucket"
                },
                {
                  "type": "object",
                  "properties": {
                    "key_id": {
                      "type": "string"
                    },
                    "key_name": {
                      "type": "string"
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorBody"
          }
        }
      }
    }
  }
}
