openapi: 3.1.0
info:
  title: GenAPI Video API
  version: 1.0.0
  description: Async video generation with Seedance 2.5.
servers:
  - url: https://api.genapi.cloud
security:
  - bearerAuth: []
paths:
  /v1/videos:
    post:
      operationId: createVideo
      summary: Create a video generation
      parameters:
        - name: Idempotency-Key
          in: header
          schema: { type: string, maxLength: 128 }
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/CreateVideoRequest' }
      responses:
        '202':
          description: Generation accepted
          content: { application/json: { schema: { $ref: '#/components/schemas/VideoGeneration' } } }
        '400': { $ref: '#/components/responses/Error' }
        '401': { $ref: '#/components/responses/Error' }
        '402': { $ref: '#/components/responses/Error' }
        '429': { $ref: '#/components/responses/Error' }
  /v1/videos/{id}:
    get:
      operationId: getVideo
      summary: Get generation status
      parameters:
        - $ref: '#/components/parameters/VideoId'
      responses:
        '200':
          description: Current generation state
          content: { application/json: { schema: { $ref: '#/components/schemas/VideoGeneration' } } }
        '404': { $ref: '#/components/responses/Error' }
  /v1/videos/{id}/content:
    get:
      operationId: downloadVideo
      summary: Stream or download a completed video
      parameters:
        - $ref: '#/components/parameters/VideoId'
        - name: Range
          in: header
          schema: { type: string, example: bytes=0-1048575 }
      responses:
        '200': { description: MP4 video, content: { video/mp4: {} } }
        '206': { description: Partial MP4 content, content: { video/mp4: {} } }
        '404': { $ref: '#/components/responses/Error' }
components:
  securitySchemes:
    bearerAuth: { type: http, scheme: bearer, bearerFormat: GenAPI key }
  parameters:
    VideoId:
      name: id
      in: path
      required: true
      schema: { type: string, format: uuid }
  responses:
    Error:
      description: API error
      content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
  schemas:
    CreateVideoRequest:
      type: object
      additionalProperties: false
      required: [model, prompt, duration_seconds]
      properties:
        model: { type: string, const: seedance-2.5 }
        prompt: { type: string, minLength: 1, maxLength: 15000 }
        mode: { type: string, enum: [text-to-video, image-to-video, reference-to-video], default: text-to-video }
        duration_seconds: { type: integer, minimum: 4, maximum: 30 }
        resolution: { type: string, enum: [480p, 720p, 1080p], default: 720p }
        aspect_ratio: { type: string, enum: [adaptive, '21:9', '16:9', '9:16', '1:1', '4:3', '3:4'], default: '16:9' }
        audio: { type: boolean, default: true }
        image_urls: { type: array, maxItems: 30, items: { type: string, format: uri, pattern: '^https://' } }
        audio_urls: { type: array, maxItems: 10, items: { type: string, format: uri, pattern: '^https://' } }
        source_video_ids: { type: array, maxItems: 10, items: { type: string, format: uuid } }
        reference_video_operation: { type: string, enum: [reference, edit, extend] }
        subject_to_image_ids: { $ref: '#/components/schemas/SubjectMap' }
        subject_to_video_ids: { $ref: '#/components/schemas/SubjectMap' }
        subject_to_audio_ids: { $ref: '#/components/schemas/SubjectMap' }
    VideoGeneration:
      type: object
      required: [id, object, model, status, cost_usd]
      properties:
        id: { type: string, format: uuid }
        object: { type: string, const: video.generation }
        model: { type: string, const: seedance-2.5 }
        status: { type: string, enum: [pending, running, completed, failed] }
        cost_usd: { type: number }
        output:
          type: object
          properties: { url: { type: string } }
        error: { $ref: '#/components/schemas/ErrorBody' }
    Error:
      type: object
      required: [error]
      properties: { error: { $ref: '#/components/schemas/ErrorBody' } }
    ErrorBody:
      type: object
      required: [code, message]
      properties:
        code: { type: string }
        message: { type: string }
        request_id: { type: string, format: uuid }
    SubjectMap:
      type: object
      description: Maps an @handle to valid zero-based indexes in the corresponding reference array.
      propertyNames: { pattern: '^[A-Za-z][A-Za-z0-9_]{0,63}$' }
      additionalProperties:
        type: array
        minItems: 1
        maxItems: 30
        items: { type: integer, minimum: 0 }
