openapi: 3.0.3
info:
  title: SiCurrent AI Music API
  version: 1.0.0
  description: |
    使用 SiCurrent 钱包创建的 API Key 异步生成音乐。
    创建任务后轮询任务状态。完成时 audio_url 仍需 API Key，download_url 是带随机令牌的完整下载地址，
    可直接交给浏览器或下载器，不需要再次携带 API Key。请像临时凭证一样妥善保管该链接。
    同一账号同一时间最多有一个音乐生成任务运行。
servers:
  - url: https://www.sicurrent.com
security:
  - bearerAuth: []
  - apiKeyHeader: []
paths:
  /api/v1/music:
    get:
      summary: 获取音乐 API 元数据和限制
      responses:
        '200':
          description: 服务元数据
          content:
            application/json:
              schema:
                type: object
        '401':
          $ref: '#/components/responses/Unauthorized'
  /api/v1/music/jobs:
    get:
      summary: 列出当前账号的音乐任务
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            minimum: 1
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 50
            default: 8
      responses:
        '200':
          description: 任务列表
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TaskList'
        '401':
          $ref: '#/components/responses/Unauthorized'
    post:
      summary: 创建异步音乐生成任务
      description: |
        只需 prompt 即可从创意开始生成完整歌曲。也可提供风格、情绪、乐器、语言、歌词等可选控制项。
        成功响应中的 poll_url 是账号隔离的任务状态地址。
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateMusicJob'
            examples:
              productFilm:
                value:
                  title: 向光而行
                  prompt: 为科技产品发布片创作一首克制、明亮、具有推进感的器乐曲
                  language: chinese
                  genre: 电子
                  mood: 坚定
                  style: Cinematic
                  instruments: 钢琴、弦乐、电子合成器
                  duration_target: 90s
                  lyrics_density: none
      responses:
        '200':
          description: 任务已提交
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobAccepted'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          description: 钱包余额不足
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: 当前账号已有音乐任务生成中
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobAccepted'
        '429':
          $ref: '#/components/responses/RateLimited'
  /api/v1/music/jobs/{taskId}:
    get:
      summary: 查询音乐任务状态与结果
      parameters:
        - $ref: '#/components/parameters/TaskId'
      responses:
        '200':
          description: 任务状态；完成后 result 包含需鉴权的 audio_url 和免 API Key 的完整 download_url
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MusicTask'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: 任务不存在或不属于当前账号
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api/v1/music/jobs/{taskId}/audio:
    get:
      summary: 播放或下载已完成的音频
      parameters:
        - $ref: '#/components/parameters/TaskId'
        - name: download
          in: query
          description: 设为 1 时以附件形式下载
          schema:
            type: string
            enum: ['0', '1']
      responses:
        '200':
          description: 音频二进制流
          content:
            audio/mpeg:
              schema:
                type: string
                format: binary
            audio/wav:
              schema:
                type: string
                format: binary
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: 任务或音频不存在
  /api/v1/music/download/{token}:
    get:
      summary: 使用随机下载令牌下载已完成的音乐
      description: download_url 指向此接口；链接本身是下载凭证，无需 API Key，请勿公开泄露。
      security: []
      parameters:
        - name: token
          in: path
          required: true
          schema:
            type: string
            minLength: 32
      responses:
        '200':
          description: 以附件形式返回音频二进制流
          content:
            audio/mpeg:
              schema:
                type: string
                format: binary
        '404':
          description: 下载令牌无效、任务不可用或内容已被清理
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API_KEY
      description: 钱包创建的 ak_ 开头 API Key
    apiKeyHeader:
      type: apiKey
      in: header
      name: X-API-Key
  parameters:
    TaskId:
      name: taskId
      in: path
      required: true
      schema:
        type: integer
        minimum: 1
  responses:
    Unauthorized:
      description: API Key 缺失、无效、已禁用或已删除
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    BadRequest:
      description: 请求参数不合法或内容安全校验未通过
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimited:
      description: 请求超过每分钟限制
      headers:
        Retry-After:
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  schemas:
    CreateMusicJob:
      type: object
      required: [prompt]
      properties:
        title:
          type: string
        prompt:
          type: string
          description: 歌曲主题、使用场景与创作要求
        language:
          type: string
          enum: [chinese, english, bilingual, japanese, thai, korean, french, spanish, multilingual]
        genre:
          type: string
        mood:
          type: string
        style:
          type: string
        tempo:
          type: string
        key:
          type: string
        instruments:
          type: string
        vocal_gender:
          type: string
        vocal_timbre:
          type: string
        vocal_style:
          type: string
        duration_target:
          type: string
        lyrics_density:
          type: string
          enum: [standard, minimal, none]
        lyrics:
          type: string
        music_prompt:
          type: string
        budget:
          type: number
          minimum: 0
          description: 可选的本次预算上限
    JobAccepted:
      type: object
      properties:
        status:
          type: string
        code:
          type: string
        message:
          type: string
        task_id:
          type: integer
        poll_url:
          type: string
          example: /api/v1/music/jobs/123
        cost:
          type: number
        balance_after:
          type: number
        budget:
          type: number
    MusicTask:
      type: object
      properties:
        status:
          type: string
          enum: [submitting, pending, processing, completed, failed]
        task_id:
          type: integer
        title:
          type: string
        progress:
          type: integer
          minimum: 0
          maximum: 100
        result:
          type: object
          additionalProperties: true
          properties:
            audio_url:
              type: string
              format: uri
              description: 完整播放地址，请求时仍需携带 API Key
            download_url:
              type: string
              format: uri
              description: 带随机令牌的完整下载地址，访问时无需 API Key
              example: https://www.sicurrent.com/api/v1/music/download/0123456789abcdef0123456789abcdef0123456789abcdef
            lyrics:
              type: string
        error_msg:
          type: string
        cost:
          type: number
        budget:
          type: number
        payment_status:
          type: string
        refunded:
          type: boolean
        created_at:
          type: string
          format: date-time
        completed_at:
          type: string
          format: date-time
    TaskList:
      type: object
      properties:
        status:
          type: string
        tasks:
          type: array
          items:
            $ref: '#/components/schemas/MusicTask'
        page:
          type: integer
        limit:
          type: integer
        total:
          type: integer
        totalPages:
          type: integer
    Error:
      type: object
      properties:
        status:
          type: string
          example: error
        error:
          type: string
        code:
          type: string
        message:
          type: string
