openapi: 3.0.3
info:
  title: VideoBGRemover API
  version: 1.6.0
  description: |
    Remove backgrounds from videos using AI-powered processing. 
    
    The VideoBGRemover API allows you to:
    - Upload videos or provide URLs for processing
    - Remove backgrounds with customizable options
    - Generate transparent videos in multiple formats
    - Compose videos on custom backgrounds (server-side)
    - Track processing status and manage credits
    
    ## Authentication
    All API requests require authentication using an API key in the `X-Api-Key` header.
    
    ## Credits System
    Video processing costs 1 credit per second of video duration.
  contact:
    name: VideoBGRemover API Support
    url: https://videobgremover.com/contact
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT

servers:
  - url: https://api.videobgremover.com
    description: Production server

security:
  - ApiKeyAuth: []

paths:
  /v1/jobs:
    post:
      operationId: createJob
      summary: Create a new video processing job
      description: |
        Create a new job for video background removal. You can either:
        1. **File Upload**: Provide filename and content_type to get an upload URL
        2. **URL Download**: Provide video_url to download from a public URL
        
        **File Limits:**
        - Formats: MP4, MOV, WebM
        - Size: 1GB maximum
        - Duration: No hard limit (processing time varies)
        
        Note: Provide either (filename + content_type) OR video_url, not both.
      tags:
        - Jobs
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/CreateJobFileUpload'
                - $ref: '#/components/schemas/CreateJobUrlDownload'
            examples:
              file_upload:
                summary: File Upload Method
                value:
                  filename: "my-video.mp4"
                  content_type: "video/mp4"
              url_download:
                summary: URL Download Method
                value:
                  video_url: "https://example.com/video.mp4"
              webm_upload:
                summary: WebM File Upload
                value:
                  filename: "my-video.webm"
                  content_type: "video/webm"
              mov_upload:
                summary: MOV File Upload
                value:
                  filename: "my-video.mov"
                  content_type: "video/mov"
      responses:
        '200':
          description: Job created successfully
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/JobCreatedFileUpload'
                  - $ref: '#/components/schemas/JobCreatedUrlDownload'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '500':
          $ref: '#/components/responses/InternalError'

  /v1/jobs/{id}/start:
    post:
      operationId: startJob
      summary: Start processing a video job
      description: |
        Start background removal processing for an uploaded video.
        
        **Important**: Credits are checked and deducted when you call this endpoint,
        not when creating the job. Processing costs 1 credit per second of video.
      tags:
        - Jobs
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: Job ID returned from job creation
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StartJobRequest'
            examples:
              default_green:
                summary: Default (Green Screen)
                value:
                  format: "mp4"
              color_background:
                summary: Color Background
                value:
                  background:
                    type: "color"
                    color: "#FF0000"
              transparent_webm:
                summary: Transparent WebM
                value:
                  background:
                    type: "transparent"
                    transparent_format: "webm_vp9"
              lottie_export:
                summary: Lottie JSON Export
                value:
                  background:
                    type: "transparent"
                    transparent_format: "lottie"
              gif_export:
                summary: Transparent GIF
                value:
                  background:
                    type: "transparent"
                    transparent_format: "gif"
              gif_export_small:
                summary: Transparent GIF (downscaled to keep file size small)
                value:
                  background:
                    type: "transparent"
                    transparent_format: "gif"
                    transform:
                      max_width: 480
                      fps: 15
              webp_export:
                summary: Transparent WebP
                value:
                  background:
                    type: "transparent"
                    transparent_format: "webp"
              pro_bundle:
                summary: Pro Bundle (Professional Workflow)
                value:
                  background:
                    type: "transparent"
                    transparent_format: "pro_bundle"
              composition_template:
                summary: Video Composition (Template)
                value:
                  background:
                    type: "composition"
                    composition:
                      template: "ai_ugc_ad"
                      background_url: "https://example.com/background.mp4"
                      background_type: "video"
                      background_audio_enabled: true
                      background_audio_volume: 0.8
              composition_custom:
                summary: Video Composition (Custom)
                value:
                  background:
                    type: "composition"
                    composition:
                      background_url: "https://example.com/background.jpg"
                      background_type: "image"
                      position: "center"
                      size_mode: "canvas_percent"
                      size_percent: 50
                      opacity: 1.0
              text_prompt_pro:
                summary: Text Prompt (Pro Model)
                value:
                  model: "videobgremover-pro"
                  prompt:
                    mode: "text"
                    text: "person wearing red jacket"
                  background:
                    type: "transparent"
                    transparent_format: "webm_vp9"
              auto_prompt_explicit:
                summary: Auto Mode (Explicit)
                value:
                  model: "videobgremover-original"
                  prompt:
                    mode: "auto"
                  background:
                    type: "transparent"
                    transparent_format: "stacked_video"
              auto_prompt_omitted:
                summary: Auto Mode (Omitted - Recommended)
                value:
                  model: "videobgremover-light"
                  background:
                    type: "color"
                    color: "#00FF00"
              multiple_exports_one_processing_call:
                summary: Multiple formats and sizes from one processing call
                value:
                  background:
                    type: "transparent"
                    transparent_format: "hevc_alpha"
                  exports:
                    - format: "stacked_video"
                      sizes: ["native", 1080, 720]
                    - format: "webm_vp9"
                      sizes: [1080, 720, 480]
                    - format: "hevc_alpha"
                      sizes: ["native", 1080, 720]
      responses:
        '200':
          description: Processing started successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobStarted'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'

  /v1/jobs/{id}/status:
    get:
      operationId: getJobStatus
      summary: Check job processing status
      description: |
        Check the current status of a video processing job and get download URLs when complete.
      tags:
        - Jobs
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: Job ID to check status for
      responses:
        '200':
          description: Job status retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobStatus'
              examples:
                job_created:
                  summary: Job just created
                  value:
                    id: "550e8400-e29b-41d4-a716-446655440000"
                    status: "created"
                    filename: "my-video.mp4"
                    created_at: "2023-12-01T10:00:00Z"
                    length_seconds: null
                    thumbnail_url: null
                    transparent_thumbnail_url: null
                    processed_video_url: null
                    processed_mask_url: null
                    message: null
                    background: null
                    output_format: null
                    export_id: null
                job_processing:
                  summary: Job currently processing
                  value:
                    id: "550e8400-e29b-41d4-a716-446655440000"
                    status: "processing"
                    filename: "my-video.mp4"
                    created_at: "2023-12-01T10:00:00Z"
                    length_seconds: 30.5
                    thumbnail_url: "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000_thumb.jpg?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Expires=3600"
                    transparent_thumbnail_url: null
                    processed_video_url: null
                    processed_mask_url: null
                    message: "Processing video with red background"
                    background:
                      type: "color"
                      color: "#FF0000"
                    output_format: "mp4"
                    export_id: "exp_red_bg_123"
                job_completed_default:
                  summary: Job completed with default green screen
                  value:
                    id: "550e8400-e29b-41d4-a716-446655440000"
                    status: "completed"
                    filename: "my-video.mp4"
                    created_at: "2023-12-01T10:00:00Z"
                    length_seconds: 30.5
                    thumbnail_url: "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000_thumb.jpg?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Expires=3600"
                    transparent_thumbnail_url: "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000_transparent_thumb.png?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Expires=3600"
                    processed_video_url: "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000.mp4?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Expires=3600"
                    processed_mask_url: "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000_mask.mp4?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Expires=3600"
                    message: "Processing completed successfully"
                    background: null
                    output_format: null
                    export_id: null
                job_completed_transparent:
                  summary: Job completed with transparent WebM
                  value:
                    id: "550e8400-e29b-41d4-a716-446655440000"
                    status: "completed"
                    filename: "my-video.mp4"
                    created_at: "2023-12-01T10:00:00Z"
                    length_seconds: 30.5
                    thumbnail_url: "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000_thumb.jpg?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Expires=3600"
                    transparent_thumbnail_url: "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000_transparent_thumb.png?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Expires=3600"
                    processed_video_url: "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000.webm?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Expires=3600"
                    processed_mask_url: "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000_mask.mp4?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Expires=3600"
                    message: "Processing completed successfully"
                    background:
                      type: "transparent"
                      transparent_format: "webm_vp9"
                    output_format: "webm"
                    export_id: "exp_webm_vp9_456"
                job_failed:
                  summary: Job failed with error
                  value:
                    id: "550e8400-e29b-41d4-a716-446655440000"
                    status: "failed"
                    filename: "my-video.mp4"
                    created_at: "2023-12-01T10:00:00Z"
                    length_seconds: null
                    thumbnail_url: null
                    transparent_thumbnail_url: null
                    processed_video_url: null
                    processed_mask_url: null
                    message: "Video too large: 1250.5MB"
                    background:
                      type: "color"
                      color: "#FF0000"
                    output_format: "mp4"
                    export_id: "exp_red_bg_123"
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'

  /v1/jobs/{id}:
    delete:
      operationId: deleteJob
      summary: Delete a video job
      description: |
        Permanently delete a video job and all associated files.

        This will delete:
        - Videos and exports
        - Database record and all related data

        **Warning**: This action cannot be undone. No credit refunds are issued for deleted jobs.

        **Authorization**: You can only delete jobs that belong to your API key's user account.
      tags:
        - Jobs
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
          description: Job ID to delete
      responses:
        '200':
          description: Job deleted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobDeleted'
              example:
                id: "550e8400-e29b-41d4-a716-446655440000"
                message: "Job deleted successfully"
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: Job not found or does not belong to user
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: "Job not found or does not belong to user"
        '500':
          $ref: '#/components/responses/InternalError'

  /v1/credits:
    get:
      operationId: getCredits
      summary: Check credit balance
      description: |
        Get your current credit balance and usage information.
      tags:
        - Credits
      responses:
        '200':
          description: Credit balance retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreditBalance'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalError'

  /v1/openapi:
    get:
      operationId: getOpenApiSpec
      summary: Get OpenAPI specification
      description: |
        Retrieve the OpenAPI 3.0 specification for this API in YAML format.
      tags:
        - API
      responses:
        '200':
          description: OpenAPI specification retrieved successfully
          headers:
            Content-Type:
              schema:
                type: string
                example: "application/x-yaml"
          content:
            application/x-yaml:
              schema:
                type: string
        '404':
          $ref: '#/components/responses/NotFound'

  /v1/webhooks/deliveries:
    get:
      operationId: getWebhookDeliveries
      summary: Get webhook delivery history
      description: |
        Retrieve the delivery history for webhooks sent for a specific video job.
        Shows all delivery attempts, their status, and any error messages.
      tags:
        - Webhooks
      parameters:
        - name: video_id
          in: query
          required: true
          schema:
            type: string
            format: uuid
          description: Video job ID to get webhook delivery history for
      responses:
        '200':
          description: Webhook delivery history retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookDeliveryHistory'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalError'

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-Api-Key
      description: API key with format `vbr_` followed by 32 characters

  schemas:
    CreateJobFileUpload:
      type: object
      required:
        - filename
        - content_type
      properties:
        filename:
          type: string
          description: Name of the video file
          example: "my-video.mp4"
        content_type:
          type: string
          description: MIME type of the video file (1GB max size)
          enum:
            - "video/mp4"
            - "video/mov"
            - "video/webm"
          example: "video/mp4"

    CreateJobUrlDownload:
      type: object
      required:
        - video_url
      properties:
        video_url:
          type: string
          format: uri
          description: Public URL of the video to download and process (1GB max size)
          example: "https://example.com/video.mp4"

    JobCreatedFileUpload:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Unique job identifier
        status:
          type: string
          enum: ["created"]
          description: Job status
        filename:
          type: string
          description: Original filename
        content_type:
          type: string
          description: File content type
        upload_url:
          type: string
          format: uri
          description: Signed URL for uploading the video file
        expires_at:
          type: string
          format: date-time
          description: Upload URL expiration time
        created_at:
          type: string
          format: date-time
          description: Job creation timestamp
        instructions:
          type: object
          properties:
            method:
              type: string
              enum: ["PUT"]
            headers:
              type: object
              properties:
                Content-Type:
                  type: string
            note:
              type: string

    JobCreatedUrlDownload:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Unique job identifier
        status:
          type: string
          enum: ["uploaded"]
          description: Job status (ready for processing)
        filename:
          type: string
          description: Extracted video title
        content_type:
          type: string
          description: Detected content type
        created_at:
          type: string
          format: date-time
          description: Job creation timestamp
        video_length_seconds:
          type: number
          description: Video duration in seconds
        message:
          type: string
          description: Success message

    StartJobRequest:
      type: object
      properties:
        format:
          type: string
          enum: ["mp4"]
          default: "mp4"
          description: Output video format
        model:
          type: string
          enum: ["videobgremover-original", "videobgremover-light", "videobgremover-pro", "videobgremover-human"]
          default: "videobgremover-original"
          description: |
            AI model for background removal:
            - **videobgremover-original**: High-quality background removal. Best for detailed segmentation and complex scenes.
            - **videobgremover-light**: Fast and efficient background removal. Optimized for speed while maintaining good quality.
            - **videobgremover-pro**: Advanced background removal for complex objects. Enables text prompting for precise segmentation.
            - **videobgremover-human**: Fast matting algorithm optimized for portraits and facing people.
        prompt:
          $ref: '#/components/schemas/Prompt'
        background:
          $ref: '#/components/schemas/BackgroundOptions'
        exports:
          type: array
          minItems: 1
          description: |
            Additional outputs rendered after the primary `background` output in the
            same processing worker invocation. Each `sizes` value creates one output;
            `native` preserves the source dimensions. Primary and additional outputs
            that are identical are deduplicated. At most 50 unique outputs are allowed.
            The primary `background` property is required when `exports` is provided.
            Numeric sizes are not currently supported for `pro_bundle`,
            `stacked_video_mask_inverted`, `mask_video`, `mask_video_inverted`, or
            `webp`; use `native` for those formats.
          items:
            $ref: '#/components/schemas/StartExportItem'
        webhook_url:
          type: string
          format: uri
          description: Webhook URL to notify when job completes or fails. **Must use HTTPS in production.**

    Prompt:
      type: object
      properties:
        mode:
          type: string
          enum: ["auto", "text"]
          default: "auto"
          description: |
            Prompting mode:
            - **auto**: Automatic background detection (default, works with all models)
            - **text**: Text-based prompt for specific subjects (only with videobgremover-pro)
        text:
          type: string
          description: 'Natural language description of the subject to keep in the video (required when mode is "text"). Examples: "person", "dog", "car with red paint"'
      required:
        - mode

    BackgroundOptions:
      type: object
      required:
        - type
      properties:
        type:
          type: string
          enum: ["color", "transparent", "composition", "blur"]
          description: Background type
        color:
          type: string
          pattern: "^#[0-9A-Fa-f]{6}$"
          description: Hex color code (required when type is "color")
          example: "#FF0000"
        transparent_format:
          type: string
          enum: ["webm_vp9", "mov_prores", "hevc_alpha", "png_sequence", "pro_bundle", "stacked_video", "stacked_video_mask_inverted", "mask_video", "mask_video_inverted", "gif", "webp", "lottie", "dotlottie"]
          description: Transparent output format (when type is "transparent")
        transform:
          $ref: '#/components/schemas/TransformOptions'
          description: |
            Optional transform applied to all transparent formats (crop, resize, fps).
            Use `max_width` and `fps` to control output size — important for `gif` and `webp`,
            where unconstrained 720p/30fps output can exceed 50MB.
        options:
          $ref: '#/components/schemas/FormatOptions'
          description: Lottie/dotlottie-specific encoding options.
        lottie_options:
          allOf:
            - $ref: '#/components/schemas/FormatOptions'
          deprecated: true
          description: Deprecated compatibility alias for `options`. If both are present, `options` wins.
        composition:
          $ref: '#/components/schemas/CompositionOptions'
          description: Composition parameters (required when type is "composition")
        blur_mode:
          type: string
          enum: ["background", "foreground"]
        blur_intensity:
          type: number
          minimum: 0
          maximum: 200
        blur_type:
          type: string
          enum: ["gaussian", "box"]

    TransformOptions:
      type: object
      description: |
        Output transform applied before encoding. Applies to all transparent formats
        (webm_vp9, mov_prores, png_sequence, gif, webp, lottie, etc.).
      properties:
        crop:
          type: object
          description: Crop region in input pixel coordinates (applied before resize)
          required: [x, y, width, height]
          properties:
            x:
              type: integer
              minimum: 0
              description: Left offset in pixels
            y:
              type: integer
              minimum: 0
              description: Top offset in pixels
            width:
              type: integer
              minimum: 1
              description: Crop width in pixels
            height:
              type: integer
              minimum: 1
              description: Crop height in pixels
        max_width:
          type: integer
          minimum: 1
          description: |
            Maximum output width in pixels. Aspect ratio is preserved — height scales
            automatically. Has no effect when the input is already narrower than `max_width`.
            Primary lever for shrinking GIF/WebP output (e.g. 480 typically cuts file size
            by ~3–4x versus 720p).
          example: 480
        fps:
          type: integer
          minimum: 1
          maximum: 60
          description: |
            Output frame rate. Lower values produce smaller files; for GIF, 12–15 fps is
            usually a good balance. Defaults to the input video's frame rate.
          example: 15
        reverse:
          type: boolean
          default: false
          description: Reverse frame order before encoding

    FormatOptions:
      type: object
      properties:
        preset:
          type: string
          enum: ["mobile", "web", "hd", "original"]
        smart_sampling:
          type: boolean
        threshold:
          type: number
          minimum: 0.1
          maximum: 2

    StartExportItem:
      type: object
      required:
        - format
      properties:
        format:
          type: string
          enum: ["webm_vp9", "mov_prores", "hevc_alpha", "png_sequence", "pro_bundle", "stacked_video", "stacked_video_mask_inverted", "mask_video", "mask_video_inverted", "gif", "webp", "lottie", "dotlottie", "color", "blur", "original"]
          description: Output format or background export type
        sizes:
          type: array
          minItems: 1
          description: |
            One output width per entry. Use `native` for no resize. The established
            `pro_bundle`, `stacked_video_mask_inverted`, `mask_video`,
            `mask_video_inverted`, and `webp` exporters currently support only
            `native` here.
          items:
            oneOf:
              - type: string
                enum: ["native"]
              - type: integer
                minimum: 1
        transform:
          allOf:
            - $ref: '#/components/schemas/TransformOptions'
          description: Optional crop, fps, or reverse settings. Do not combine `sizes` with `transform.max_width`.
        options:
          $ref: '#/components/schemas/FormatOptions'
          description: Lottie/dotlottie-specific encoding options
        lottie_options:
          allOf:
            - $ref: '#/components/schemas/FormatOptions'
          deprecated: true
          description: Deprecated compatibility alias for `options`. If both are present, `options` wins.
        background:
          type: object
          description: Required when format is `color`
          properties:
            color:
              type: string
              pattern: "^#[0-9A-Fa-f]{6}$"
        blur:
          type: object
          description: Settings used when format is `blur`
          properties:
            mode:
              type: string
              enum: ["background", "foreground"]
            intensity:
              type: number
              minimum: 0
              maximum: 200
            type:
              type: string
              enum: ["gaussian", "box"]

    CompositionOptions:
      type: object
      oneOf:
        - $ref: '#/components/schemas/CompositionTemplate'
        - $ref: '#/components/schemas/CompositionCustom'
    
    CompositionTemplate:
      type: object
      required:
        - template
      properties:
        template:
          type: string
          enum: ["ai_ugc_ad", "centered", "picture_in_picture", "fullscreen"]
          description: |
            Pre-configured composition template:
            - **ai_ugc_ad**: 9:16 centered layout optimized for social media ads
            - **centered**: Centered foreground with contain sizing
            - **picture_in_picture**: Small foreground in bottom-right corner
            - **fullscreen**: Foreground covers entire canvas
          example: "ai_ugc_ad"
        background_url:
          type: string
          format: uri
          description: URL to background image or video (required)
          example: "https://example.com/background.mp4"
        background_type:
          type: string
          enum: ["image", "video"]
          description: Type of background (auto-detected from URL if not specified)
        background_audio_enabled:
          type: boolean
          default: false
          description: Enable background audio (only for video backgrounds)
        background_audio_volume:
          type: number
          minimum: 0
          maximum: 1
          default: 1.0
          description: Background audio volume (0.0 to 1.0)
        export_format:
          type: string
          enum: ["h264"]
          default: "h264"
          description: Export video codec
        export_crf:
          type: integer
          minimum: 0
          maximum: 51
          default: 23
          description: Export quality (lower = better quality, 0-51)
    
    CompositionCustom:
      type: object
      required:
        - background_url
        - background_type
      properties:
        background_url:
          type: string
          format: uri
          description: URL to background image or video
          example: "https://example.com/background.mp4"
        background_type:
          type: string
          enum: ["color", "image", "video"]
          description: Type of background
        background_color:
          type: string
          pattern: "^#[0-9A-Fa-f]{6}$"
          description: Hex color (when background_type is "color")
        background_audio_enabled:
          type: boolean
          default: false
          description: Enable background audio (video backgrounds only)
        background_audio_volume:
          type: number
          minimum: 0
          maximum: 1
          default: 1.0
          description: Background audio volume
        position:
          type: string
          enum: ["center", "top_left", "top_center", "top_right", "center_left", "center_right", "bottom_left", "bottom_center", "bottom_right"]
          default: "center"
          description: Anchor position for foreground placement
        offset_x:
          type: integer
          default: 0
          description: Horizontal offset in pixels from anchor
        offset_y:
          type: integer
          default: 0
          description: Vertical offset in pixels from anchor
        size_mode:
          type: string
          enum: ["contain", "cover", "canvas_percent", "px", "scale", "fit_width", "fit_height"]
          default: "contain"
          description: |
            Foreground sizing mode:
            - **contain**: Fit within canvas, preserve aspect ratio
            - **cover**: Fill canvas, preserve aspect ratio (may crop)
            - **canvas_percent**: Size as percentage of canvas
            - **px**: Exact pixel dimensions
            - **scale**: Scale relative to original size
            - **fit_width**: Fit to canvas width
            - **fit_height**: Fit to canvas height
        size_percent:
          type: number
          description: Size percentage (when size_mode is "canvas_percent")
        size_width:
          type: number
          description: Width value (depends on size_mode)
        size_height:
          type: number
          description: Height value (depends on size_mode)
        opacity:
          type: number
          minimum: 0
          maximum: 1
          default: 1.0
          description: Foreground opacity (0.0 to 1.0)
        export_format:
          type: string
          enum: ["h264"]
          default: "h264"
          description: Export video codec
        export_crf:
          type: integer
          minimum: 0
          maximum: 51
          default: 23
          description: Export quality (lower = better, 0-51)

    JobStarted:
      type: object
      properties:
        id:
          type: string
          format: uuid
          description: Job identifier
        export_id:
          type: string
          format: uuid
          description: Export identifier (when background is specified)
        batch_id:
          type: string
          format: uuid
          description: Batch identifier when additional exports were requested
        total_exports:
          type: integer
          description: Number of unique primary and additional outputs in the batch
        exports:
          type: array
          description: Queued outputs when additional exports were requested
          items:
            type: object
            properties:
              export_id:
                type: string
                format: uuid
              format:
                type: string
              status:
                type: string
                enum: ["queued"]
              transform:
                $ref: '#/components/schemas/TransformOptions'
        status:
          type: string
          enum: ["processing"]
          description: Processing status
        created_at:
          type: string
          format: date-time
          description: Processing start time
        creditsUsed:
          type: number
          description: Credits deducted for this job
        video_length_seconds:
          type: number
          description: Video duration in seconds
        background:
          $ref: '#/components/schemas/BackgroundOptions'

    JobStatus:
      type: object
      required:
        - id
        - status
        - filename
        - created_at
      properties:
        id:
          type: string
          format: uuid
          description: Job identifier
        export_id:
          type: string
          format: uuid
          description: Export identifier (only present for API calls with background)
          nullable: true
        status:
          type: string
          enum: ["created", "uploaded", "processing", "completed", "failed"]
          description: Current job status
        filename:
          type: string
          description: Original filename
        created_at:
          type: string
          format: date-time
          description: Job creation time
        length_seconds:
          type: number
          description: Video duration in seconds
          nullable: true
        thumbnail_url:
          type: string
          format: uri
          description: Signed URL for video thumbnail
          nullable: true
        transparent_thumbnail_url:
          type: string
          format: uri
          description: Signed URL for transparent thumbnail
          nullable: true
        processed_video_url:
          type: string
          format: uri
          description: Signed URL for processed video (when completed)
          nullable: true
        processed_mask_url:
          type: string
          format: uri
          description: Signed URL for video mask (when completed)
          nullable: true
        message:
          type: string
          description: Status message
          nullable: true
        background:
          allOf:
            - $ref: '#/components/schemas/BackgroundOptions'
          description: Background options (only present for API calls with background)
          nullable: true
        output_format:
          type: string
          description: Output file format (only present for API calls with background)
          nullable: true

    JobDeleted:
      type: object
      required:
        - id
        - message
      properties:
        id:
          type: string
          format: uuid
          description: ID of the deleted job
        message:
          type: string
          description: Success message
          example: "Job deleted successfully"

    CreditBalance:
      type: object
      properties:
        user_id:
          type: string
          format: uuid
          description: User identifier
        total_credits:
          type: number
          description: Total credits purchased
        remaining_credits:
          type: number
          description: Credits available for use
        used_credits:
          type: number
          description: Credits already consumed

    WebhookDeliveryHistory:
      type: object
      properties:
        video_id:
          type: string
          format: uuid
          description: Video job ID
        total_deliveries:
          type: integer
          description: Total number of delivery attempts
        deliveries:
          type: array
          items:
            $ref: '#/components/schemas/WebhookDelivery'
          description: List of webhook delivery attempts

    WebhookDelivery:
      type: object
      properties:
        event_type:
          type: string
          enum: ["job.started", "job.completed", "job.failed"]
          description: Type of event that triggered the webhook
        webhook_url:
          type: string
          format: uri
          description: Webhook URL that was called
        attempt_number:
          type: integer
          description: Delivery attempt number (starts at 1)
        delivery_status:
          type: string
          enum: ["pending", "delivered", "failed"]
          description: Current delivery status
        http_status_code:
          type: integer
          description: HTTP status code from the webhook call
          nullable: true
        error_message:
          type: string
          description: Error message if delivery failed
          nullable: true
        scheduled_at:
          type: string
          format: date-time
          description: When the delivery was scheduled
        delivered_at:
          type: string
          format: date-time
          description: When the delivery was completed (successful or failed)
          nullable: true
        payload:
          type: object
          description: Webhook payload that was sent
        created_at:
          type: string
          format: date-time
          description: When the delivery record was created

    APIError:
      type: object
      properties:
        error:
          type: string
          description: Error message
        details:
          type: string
          description: Additional error details

  responses:
    BadRequest:
      description: Bad request - Invalid parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/APIError'
          examples:
            invalid_background:
              summary: Invalid background color
              value:
                error: "Invalid background color format. Must be hex color like #FF0000"
            missing_params:
              summary: Missing required parameters
              value:
                error: "Must provide either (filename + content_type) OR video_url"

    Unauthorized:
      description: Unauthorized - Invalid or missing API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/APIError'
          example:
            error: "Invalid API key"

    PaymentRequired:
      description: Payment Required - Insufficient credits
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/APIError'
          example:
            error: "Not enough credits available"

    PayloadTooLarge:
      description: Payload too large - File exceeds 1GB limit
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/APIError'
          examples:
            file_too_large:
              summary: Video file too large
              value:
                error: "Video too large: 1250.5MB"
            url_too_large:
              summary: URL video too large
              value:
                error: "Video too large: 1250.5MB"

    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/APIError'
          example:
            error: "Job not found or does not belong to user"

    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/APIError'
          example:
            error: "Internal server error"

tags:
  - name: Jobs
    description: Video processing job management
  - name: Credits
    description: Credit balance and usage
  - name: API
    description: API metadata and documentation
  - name: Webhooks
    description: Webhook delivery and history
