{
  "openapi": "3.1.0",
  "info": {
    "title": "算力汇 · AI API",
    "version": "1.1.0",
    "summary": "OpenAI / Anthropic / Gemini 兼容的多模型 API，含异步视频任务。",
    "description": "统一接入文本、图像、视频模型。\n\n**认证**：`Authorization: Bearer sk-...`；Anthropic 协议用 `x-api-key`。\n\n**视频是异步任务**：`POST /videos` 提交 → `GET /videos/{id}` 轮询 → `GET /videos/{id}/content` 取成片。也可用 `webhook_url` 让平台主动推送。\n\n**防重复扣费**：提交时带 `Idempotency-Key`，24 小时内同 Key 同请求体只会产生一个任务。\n\n**先报价后下单**：`POST /videos/quote` 拿报价单，提交时带 `quote_id` 锁价；价格若在期间变动会明确返回 `quote_price_changed`，不会静默变价。",
    "x-generated-at": 1791386510
  },
  "servers": [
    {
      "url": "https://api.ideamine.cn/v1",
      "description": "算力汇 API（OpenAI 兼容）"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Chat",
      "description": "文本对话"
    },
    {
      "name": "Models",
      "description": "模型列表"
    },
    {
      "name": "Video",
      "description": "异步视频生成（Seedance 系列）"
    },
    {
      "name": "Webhooks",
      "description": "任务完成事件推送"
    }
  ],
  "paths": {
    "/chat/completions": {
      "post": {
        "tags": [
          "Chat"
        ],
        "summary": "对话补全（OpenAI 兼容）",
        "operationId": "createChatCompletion",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "model",
                  "messages"
                ],
                "properties": {
                  "model": {
                    "type": "string",
                    "description": "可用稳定别名（`video-fast` / `video-quality`）或具体型号；建议用别名，方便后续换上游",
                    "examples": [
                      "deepseek-v4-flash",
                      "glm-5.3",
                      "kimi-k3"
                    ]
                  },
                  "messages": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/ChatMessage"
                    }
                  },
                  "stream": {
                    "type": "boolean",
                    "default": false,
                    "description": "SSE 流式输出"
                  },
                  "max_tokens": {
                    "type": "integer"
                  },
                  "temperature": {
                    "type": "number"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "请求不合法",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "令牌无效",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "402": {
            "description": "额度不足",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "触发限流",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "503": {
            "description": "无可用渠道",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/capabilities": {
      "get": {
        "tags": [
          "Models"
        ],
        "summary": "模型能力矩阵（真实时长 / 分辨率 / 状态）",
        "description": "公开每个模型**真实的**时长区间与分辨率，而不是网关的通用上限。网关上限不能等同于具体模型的能力。",
        "operationId": "listCapabilities",
        "responses": {
          "200": {
            "description": "能力矩阵",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "model": {
                            "type": "string"
                          },
                          "durations": {
                            "type": "array",
                            "items": {
                              "type": "integer"
                            },
                            "description": "[最短, 最长] 秒"
                          },
                          "resolutions": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "status": {
                            "enum": [
                              "stable",
                              "preview"
                            ]
                          },
                          "alias_of": {
                            "type": "string",
                            "description": "稳定别名指向的精确模型"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/models": {
      "get": {
        "tags": [
          "Models"
        ],
        "summary": "列出可用模型",
        "operationId": "listModels",
        "responses": {
          "200": {
            "description": "模型列表",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "object": {
                            "const": "model"
                          },
                          "owned_by": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/videos/quote": {
      "post": {
        "tags": [
          "Video"
        ],
        "summary": "为一次视频生成报价（价格可锁）",
        "description": "报价单有效期 30 分钟。提交时带上 `quote_id`；若价格在期间变动，会返回 `409 quote_price_changed`，**不会静默按新价扣费**。",
        "operationId": "createVideoQuote",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "model"
                ],
                "properties": {
                  "model": {
                    "type": "string",
                    "enum": [
                      "Doubao-Seedance-2.0-fast",
                      "Doubao-Seedance-2.0",
                      "Doubao-Seedance-2.0-test",
                      "Doubao-Seedance-2.5-test",
                      "video-fast",
                      "video-quality"
                    ]
                  },
                  "seconds": {
                    "type": "string",
                    "description": "时长（秒），字符串。不传按 4 秒",
                    "examples": [
                      "4"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "报价单",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quote"
                }
              }
            }
          },
          "400": {
            "description": "参数不合法（含 invalid_duration / invalid_resolution）",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "该模型没有定价（model_not_found）",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/videos": {
      "post": {
        "tags": [
          "Video"
        ],
        "summary": "提交视频生成任务（异步）",
        "description": "立刻返回任务对象，**不会等待生成完成**（通常 2~5 分钟）。\n\n可选请求头 `Idempotency-Key`：24 小时内同 Key + 同请求体只会产生一个任务，重试不会重复扣费；同 Key 换请求体会返回 `409 idempotency_key_reuse`。\n\n可选字段 `webhook_url` / `webhook_secret`：任务到终态时平台主动推送事件。轮换密钥时同时传 `webhook_secret`（新）与 `webhook_secret_prev`（旧），我们会用两把各签一次，你用任一都能验签，过渡结束后去掉旧的那把即可。",
        "operationId": "createVideo",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "model",
                  "prompt"
                ],
                "properties": {
                  "model": {
                    "type": "string",
                    "enum": [
                      "Doubao-Seedance-2.0-fast",
                      "Doubao-Seedance-2.0",
                      "Doubao-Seedance-2.0-test",
                      "Doubao-Seedance-2.5-test",
                      "video-fast",
                      "video-quality"
                    ],
                    "description": "可用稳定别名（video-fast / video-quality）或具体型号"
                  },
                  "prompt": {
                    "type": "string",
                    "description": "画面描述；写清「主体 + 动作 + 镜头」效果最好"
                  },
                  "seconds": {
                    "type": "string",
                    "default": "4",
                    "description": "时长（秒），**必须字符串**，默认 4。**各模型范围不同**（2.0 系列 4~12 秒、2.5 系列 2~30 秒），越界返回 `invalid_duration`。可用 `duration` 传整数，两者等价"
                  },
                  "duration": {
                    "type": "integer",
                    "description": "时长的整数写法（等价于 seconds）。兼容期两种都接受，服务端会归一化；归一化发生在幂等指纹之前，所以 duration:4 与 seconds:\"4\" 视为同一请求。"
                  },
                  "ratio": {
                    "type": "string",
                    "enum": [
                      "16:9",
                      "9:16"
                    ],
                    "description": "画面比例。不传会由 size 自动推导；不支持的取值返回 invalid_ratio"
                  },
                  "resolution": {
                    "type": "string",
                    "description": "分辨率的另一种写法（等价于 size），支持 480p / 720p / 1080p 简写"
                  },
                  "quote_id": {
                    "type": "string",
                    "description": "来自 /videos/quote，用于锁价"
                  },
                  "size": {
                    "type": "string",
                    "description": "画面尺寸。`1280x720`（横屏 16:9，默认）／`720x1280`（竖屏 9:16）／`1792x1024`／`1024x1792`",
                    "default": "1280x720",
                    "enum": [
                      "1280x720",
                      "720x1280",
                      "1792x1024",
                      "1024x1792"
                    ]
                  },
                  "webhook_url": {
                    "type": "string",
                    "format": "uri",
                    "description": "任务完成时的回调地址（也可用请求头 X-Webhook-Url）"
                  },
                  "webhook_secret": {
                    "type": "string",
                    "description": "用于对回调做 HMAC 签名"
                  },
                  "webhook_secret_prev": {
                    "type": "string",
                    "description": "密钥轮换过渡期用：上一把密钥。给了它，我们会用新旧两把密钥各签一次，你用任一都能验签，实现零停机换密钥"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "已受理",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoTask"
                }
              }
            }
          },
          "400": {
            "description": "参数不合法（含 invalid_duration）",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "402": {
            "description": "额度不足（insufficient_user_quota）",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "报价单冲突（quote_price_changed / quote_duration_mismatch / quote_already_used 等）",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/videos/{task_id}": {
      "get": {
        "tags": [
          "Video"
        ],
        "summary": "查询任务状态与账单",
        "operationId": "getVideo",
        "parameters": [
          {
            "$ref": "#/components/parameters/TaskId"
          }
        ],
        "responses": {
          "200": {
            "description": "任务对象（含 expires_at 与 billing）",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoTask"
                }
              }
            }
          },
          "404": {
            "description": "任务不存在",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/videos/{task_id}/content": {
      "get": {
        "tags": [
          "Video"
        ],
        "summary": "下载成片（MP4）",
        "description": "**上游地址有效期 24 小时**（且限 100 次下载），过期后无法再取。建议取到后立刻转存到自己的对象存储。响应 `expires_at` 字段给出确切失效时间。",
        "operationId": "getVideoContent",
        "parameters": [
          {
            "$ref": "#/components/parameters/TaskId"
          }
        ],
        "responses": {
          "200": {
            "description": "MP4 二进制",
            "content": {
              "video/mp4": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "410": {
            "description": "任务尚未完成（artifact_gone）",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "502": {
            "description": "上游取片失败（artifact_upstream_auth_failed / artifact_upstream_timeout）",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "videoCompleted": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "视频任务到达终态",
        "description": "任务 `completed` 或 `failed` 时推送到你提交时给的 `webhook_url`。\n\n**验签**：`signed = f\"{timestamp}.\" + raw_body`，`signature = \"sha256=\" + hex(hmac_sha256(secret, signed))`；轮换过渡期会多一个 `X-Webhook-Signature-Prev` 头（用上一把密钥签的），两个头**任一验过即可**；另有 `X-Webhook-Signature-Algorithm: sha256` 标明算法。请同时校验时间戳（建议 5 分钟窗口）防重放，并用常量时间比较。\n\n**重试**：30s → 2m → 10m → 1h → 6h → 24h，共 6 次。请以 `event_id` 去重（重试可能重复投递）。",
        "operationId": "videoEvent",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "接收成功（2xx 即视为成功）"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "`Authorization: Bearer sk-...`"
      }
    },
    "parameters": {
      "TaskId": {
        "name": "task_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "examples": [
          "task_710pIEcWFjYyhEFkgfMaOX3FgwR9O6pN"
        ]
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "maxLength": 200
        },
        "description": "你的订单号或业务主键；重试时原样再发即可"
      }
    },
    "schemas": {
      "ChatMessage": {
        "type": "object",
        "required": [
          "role",
          "content"
        ],
        "properties": {
          "role": {
            "enum": [
              "system",
              "user",
              "assistant"
            ]
          },
          "content": {
            "type": "string"
          }
        }
      },
      "ApiError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "invalid_request",
                  "invalid_api_key",
                  "insufficient_user_quota",
                  "model_not_found",
                  "token_model_denied",
                  "invalid_duration",
                  "invalid_resolution",
                  "invalid_ratio",
                  "invalid_parameters",
                  "artifact_gone",
                  "artifact_upstream_auth_failed",
                  "artifact_upstream_timeout",
                  "content_rejected",
                  "video_generation_failed",
                  "task_expired",
                  "upstream_timeout",
                  "upstream_rate_limited",
                  "upstream_quota_exceeded",
                  "idempotency_key_reuse",
                  "quote_not_found",
                  "quote_expired",
                  "quote_price_changed",
                  "quote_duration_mismatch",
                  "quote_model_mismatch",
                  "quote_already_used",
                  "quote_token_mismatch",
                  "not_logged_in",
                  "rate_limit_exceeded"
                ]
              },
              "message": {
                "type": "string"
              },
              "type": {
                "type": "string"
              }
            }
          },
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "data": {
            "type": [
              "object",
              "null"
            ]
          }
        }
      },
      "Quote": {
        "type": "object",
        "properties": {
          "quote_id": {
            "type": "string"
          },
          "currency": {
            "const": "CNY"
          },
          "model": {
            "type": "string"
          },
          "seconds": {
            "type": "integer"
          },
          "unit_price": {
            "type": "number",
            "description": "¥/秒"
          },
          "estimated_cost": {
            "type": "number",
            "description": "预计总价（元）"
          },
          "quota": {
            "type": "integer",
            "description": "会扣减的额度单位"
          },
          "duration_limit": {
            "type": "object",
            "properties": {
              "min": {
                "type": "integer"
              },
              "max": {
                "type": "integer"
              }
            }
          },
          "expires_at": {
            "type": "integer",
            "description": "报价单失效时间（Unix 秒）"
          }
        }
      },
      "VideoBilling": {
        "type": "object",
        "description": "该任务的账单明细",
        "properties": {
          "currency": {
            "const": "CNY"
          },
          "unit_price": {
            "type": [
              "number",
              "null"
            ],
            "description": "¥/秒"
          },
          "seconds": {
            "type": [
              "number",
              "null"
            ]
          },
          "reserved": {
            "type": "number",
            "description": "提交时预扣（元）"
          },
          "settled": {
            "type": "number",
            "description": "实际结算（元）；失败任务为 0"
          },
          "refunded": {
            "type": "number",
            "description": "已退还（元）"
          },
          "quota": {
            "type": "object",
            "properties": {
              "reserved": {
                "type": "integer"
              },
              "settled": {
                "type": "integer"
              },
              "refunded": {
                "type": "integer"
              }
            }
          }
        }
      },
      "VideoTask": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "const": "video"
          },
          "model": {
            "type": "string"
          },
          "status": {
            "enum": [
              "queued",
              "in_progress",
              "completed",
              "failed",
              "rejected",
              "expired"
            ],
            "description": "queued 排队 → in_progress 生成中 → completed 完成；failed 技术失败；rejected 内容安全拒绝（全额退还）；expired 超过 6 小时未终结，按超时处理。cancelled 不可用 —— 上游不提供取消接口。"
          },
          "requested_duration": {
            "type": [
              "number",
              "null"
            ],
            "description": "请求时长（秒）"
          },
          "actual_duration": {
            "type": [
              "number",
              "null"
            ],
            "description": "实际时长（秒），completed 时等于结算时长"
          },
          "progress": {
            "type": [
              "integer",
              "string"
            ]
          },
          "created_at": {
            "type": "integer"
          },
          "completed_at": {
            "type": "integer"
          },
          "expires_at": {
            "type": "integer",
            "description": "成片可下载的截止时间（完成时间 + 24 小时）"
          },
          "billing": {
            "$ref": "#/components/schemas/VideoBilling"
          },
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "invalid_request",
                  "invalid_api_key",
                  "insufficient_user_quota",
                  "model_not_found",
                  "token_model_denied",
                  "invalid_duration",
                  "invalid_resolution",
                  "invalid_ratio",
                  "invalid_parameters",
                  "artifact_gone",
                  "artifact_upstream_auth_failed",
                  "artifact_upstream_timeout",
                  "content_rejected",
                  "video_generation_failed",
                  "task_expired",
                  "upstream_timeout",
                  "upstream_rate_limited",
                  "upstream_quota_exceeded",
                  "idempotency_key_reuse",
                  "quote_not_found",
                  "quote_expired",
                  "quote_price_changed",
                  "quote_duration_mismatch",
                  "quote_model_mismatch",
                  "quote_already_used",
                  "quote_token_mismatch",
                  "not_logged_in",
                  "rate_limit_exceeded"
                ]
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      },
      "WebhookEvent": {
        "type": "object",
        "properties": {
          "event_id": {
            "type": "string",
            "description": "事件唯一 id，用于去重"
          },
          "event": {
            "enum": [
              "video.completed",
              "video.failed"
            ]
          },
          "task_id": {
            "type": "string"
          },
          "status": {
            "enum": [
              "completed",
              "failed"
            ]
          },
          "progress": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "fail_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "integer"
          },
          "timestamp": {
            "type": "integer"
          },
          "attempt": {
            "type": "integer"
          }
        }
      }
    }
  },
  "x-video-duration-limits": {
    "Doubao-Seedance-2.0-fast": {
      "min": 4,
      "max": 12
    },
    "Doubao-Seedance-2.0": {
      "min": 4,
      "max": 12
    },
    "Doubao-Seedance-2.0-test": {
      "min": 4,
      "max": 12
    },
    "Doubao-Seedance-2.5-test": {
      "min": 2,
      "max": 30
    },
    "video-fast": {
      "min": 4,
      "max": 12
    },
    "video-quality": {
      "min": 4,
      "max": 12
    }
  }
}