openapi: 3.0.3
info:
  title: SiCurrent AI Design API
  version: 1.0.0
  description: |
    使用 SiCurrent 钱包创建的 API Key 调用与网页端相同的硅基涌动 AI 设计能力。
    参考图采用两步式调用：先上传图片获得私有 asset_id，再在设计任务中引用该 ID。
    单张图片不得超过 10 MB；每个任务最多 5 张去重后的参考图。相同账号重复上传内容相同的图片时，
    服务端按 SHA-256 返回原 asset_id，不会重复落盘，也不会把重复图片传给模型。
    设计结果异步生成；创建任务后轮询 job 或 task 接口获取结果。任务完成后的 download_url 是带随机
    令牌的完整下载地址，可直接交给浏览器或下载器，不需要再次携带 API Key。
servers:
  - url: https://www.sicurrent.com
security:
  - bearerAuth: []
  - apiKeyHeader: []
paths:
  /api/v1/design:
    get:
      summary: 获取 AI 设计服务元数据、品类、参考图角色和限制
      responses:
        '200':
          description: 服务元数据
          content:
            application/json:
              schema:
                type: object
        '401':
          $ref: '#/components/responses/Unauthorized'
  /api/v1/design/assets:
    post:
      summary: 上传一张私有参考图片
      description: |
        图片仅对当前 API Key 所属账号可见。支持 JPG、PNG、WebP、GIF，单张最大 10 MB。
        内容重复时返回 HTTP 200、原 asset.id 和 deduplicated=true；新图片返回 HTTP 201。
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required: [file]
              properties:
                file:
                  type: string
                  format: binary
      responses:
        '200':
          description: 内容重复，复用已有资产
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AssetResponse'
        '201':
          description: 新资产已创建
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AssetResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '413':
          description: 图片超过 10 MB
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/RateLimited'
  /api/v1/design/jobs:
    post:
      summary: 创建异步 AI 设计任务
      description: |
        服务会先使用文本模型编译专业设计提示词，再提交 1 至 6 个图片生成子任务。
        references 中重复的 asset_id 会自动移除，因此同一张参考图不会重复传给模型。
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateJobRequest'
            examples:
              posterWithReferences:
                summary: 使用品牌与构图参考图生成两版海报
                value:
                  name: 夏季发布会海报
                  design_type: poster
                  brief: 为 8 月 28 日的新品发布会设计一张克制、现代、适合手机传播的竖版主视觉。
                  ratio: '3:4'
                  variant_count: 2
                  references:
                    - asset_id: asset_example_brand
                      role: brand
                    - asset_id: asset_example_layout
                      role: composition
                  options:
                    audience: 科技行业客户
                    content_language: zh-CN
      responses:
        '202':
          description: 设计任务已进入生成队列
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobAcceptedResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: 参考图不存在或不属于当前账号
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/RateLimited'
        '502':
          description: 文本模型未能编译有效设计提示词
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api/v1/design/jobs/{jobId}:
    get:
      summary: 获取设计任务及全部变体的状态和结果
      parameters:
        - $ref: '#/components/parameters/JobId'
      responses:
        '200':
          description: 任务状态；完成后各 task.output_files 包含生成文件
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/v1/design/jobs/{jobId}/cancel:
    post:
      summary: 取消尚未结束的设计子任务
      parameters:
        - $ref: '#/components/parameters/JobId'
      responses:
        '200':
          description: 取消结果
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/v1/design/tasks/{taskId}:
    get:
      summary: 获取单个设计变体的状态和结果
      parameters:
        - $ref: '#/components/parameters/TaskId'
      responses:
        '200':
          description: 设计子任务
          content:
            application/json:
              schema:
                type: object
                required: [status, task]
                properties:
                  status:
                    type: string
                    enum: [success]
                  task:
                    $ref: '#/components/schemas/Task'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/v1/design/tasks/{taskId}/download:
    get:
      summary: 下载单个设计变体的第一份生成文件
      parameters:
        - $ref: '#/components/parameters/TaskId'
      responses:
        '307':
          description: 重定向到生成文件
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: 子任务或生成文件尚不可用
  /api/v1/design/download/{token}:
    get:
      summary: 使用随机下载令牌下载已完成的设计文件
      description: download_url 指向此接口；链接本身是下载凭证，无需 API Key，请勿公开泄露。
      security: []
      parameters:
        - name: token
          in: path
          required: true
          schema:
            type: string
            minLength: 32
      responses:
        '307':
          description: 重定向到生成文件
        '404':
          description: 下载令牌无效、任务或生成文件不可用
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: 'Authorization: Bearer ak_xxx'
    apiKeyHeader:
      type: apiKey
      in: header
      name: X-API-Key
  parameters:
    JobId:
      name: jobId
      in: path
      required: true
      schema:
        type: string
        pattern: '^project_'
    TaskId:
      name: taskId
      in: path
      required: true
      schema:
        type: string
        pattern: '^task_'
  responses:
    BadRequest:
      description: 参数、图片格式或参考图角色无效
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: API Key 缺失、无效、已禁用或已删除
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: 资源不存在或不属于当前账号
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimited:
      description: 超过速率限制；响应含 Retry-After
      headers:
        Retry-After:
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  schemas:
    Error:
      type: object
      required: [status, error]
      properties:
        status:
          type: string
          enum: [error]
        error:
          type: string
        message:
          type: string
    Asset:
      type: object
      required: [id, original_name, mime_type, size, sha256, deduplicated, created_at]
      properties:
        id:
          type: string
          example: asset_E1vR7y8gX2wP4mN6
        original_name:
          type: string
        mime_type:
          type: string
          enum: [image/jpeg, image/png, image/webp, image/gif]
        size:
          type: integer
          format: int64
          maximum: 10485760
        sha256:
          type: string
          pattern: '^[a-f0-9]{64}$'
        deduplicated:
          type: boolean
        created_at:
          type: string
          format: date-time
    AssetResponse:
      type: object
      required: [status, asset]
      properties:
        status:
          type: string
          enum: [success]
        asset:
          $ref: '#/components/schemas/Asset'
    Reference:
      type: object
      required: [asset_id, role]
      properties:
        asset_id:
          type: string
        role:
          type: string
          description: 该图片仅在哪个设计维度提供参考
          enum: [structure, style, color_cmf, brand, composition]
    JobOptions:
      type: object
      properties:
        audience:
          type: string
        product_type:
          type: string
        structure:
          type: string
        material:
          type: string
        must_keep:
          type: string
        must_avoid:
          type: string
        style_preset:
          type: string
        variation_level:
          type: integer
          minimum: 1
          maximum: 5
        content_language:
          type: string
          enum: [zh-CN, zh-TW, en, ja, ko, es, fr, de, pt, ar]
    CreateJobRequest:
      type: object
      required: [design_type, brief, variant_count]
      properties:
        name:
          type: string
          maxLength: 255
        design_type:
          type: string
          enum: [toothbrush, personal-care, toothpaste, packaging, home, appliance, knowledge-summary, meeting-invitation, personal-introduction, poster]
        brief:
          type: string
          minLength: 1
          maxLength: 4000
        ratio:
          type: string
          enum: ['1:1', '4:3', '3:4', '9:16', '16:9']
        variant_count:
          type: integer
          minimum: 1
          maximum: 6
        output_format:
          type: string
          enum: [single, three_view]
        text_model_config_name:
          type: string
          description: 可选；留空时使用账号默认文本模型
        image_model_config_name:
          type: string
          description: 可选；留空时使用账号默认图片模型
        image_template:
          type: string
          maxLength: 3000
        references:
          type: array
          maxItems: 5
          description: 重复 asset_id 会被自动移除
          items:
            $ref: '#/components/schemas/Reference'
        options:
          $ref: '#/components/schemas/JobOptions'
    JobAcceptedResponse:
      type: object
      required: [status, job]
      properties:
        status:
          type: string
          enum: [success]
        job:
          type: object
          required: [id, status, progress, design_type, variant_count, task_ids]
          properties:
            id:
              type: string
            status:
              type: string
              enum: [processing]
            progress:
              type: number
            design_type:
              type: string
            variant_count:
              type: integer
            task_ids:
              type: array
              items:
                type: string
            references:
              type: array
              items:
                $ref: '#/components/schemas/Reference'
            created_at:
              type: string
              format: date-time
    OutputFile:
      type: object
      properties:
        id:
          type: integer
        taskId:
          type: string
        filePath:
          type: string
        fileName:
          type: string
        fileType:
          type: string
        fileSize:
          type: integer
          format: int64
        url:
          type: string
    Task:
      type: object
      required: [id, status, progress, output_files, download_url]
      properties:
        id:
          type: string
        status:
          type: string
          enum: [queued, processing, completed, failed, cancelled]
        progress:
          type: number
          minimum: 0
          maximum: 100
        model_provider:
          type: string
        model_name:
          type: string
        output_files:
          type: array
          items:
            $ref: '#/components/schemas/OutputFile'
        error_message:
          type: string
        download_url:
          type: string
          format: uri
          nullable: true
          description: 完成且生成文件可用后，返回带随机令牌的完整下载地址，访问时无需 API Key；生成中、失败或取消时为 null
          example: https://www.sicurrent.com/api/v1/design/download/0123456789abcdef0123456789abcdef0123456789abcdef
        created_at:
          type: string
          format: date-time
        started_at:
          type: string
          format: date-time
          nullable: true
        completed_at:
          type: string
          format: date-time
          nullable: true
        updated_at:
          type: string
          format: date-time
    JobResponse:
      type: object
      required: [status, job]
      properties:
        status:
          type: string
          enum: [success]
        job:
          type: object
          required: [id, name, status, progress, tasks]
          properties:
            id:
              type: string
            name:
              type: string
            status:
              type: string
              enum: [queued, processing, completed, partially_completed, failed, cancelled]
            progress:
              type: number
              minimum: 0
              maximum: 100
            tasks:
              type: array
              items:
                $ref: '#/components/schemas/Task'
            created_at:
              type: string
              format: date-time
            updated_at:
              type: string
              format: date-time
