components:
  schemas:
    APIError:
      additionalProperties: false
      properties:
        error:
          $ref: "#/components/schemas/ErrorDetail"
      required:
        - error
      type: object
    Asset:
      additionalProperties: false
      properties:
        asset_id:
          type: string
        last_frame_asset_id:
          type: string
        metadata:
          $ref: "#/components/schemas/OutputMetadata"
        outputs:
          items:
            $ref: "#/components/schemas/DeliveredOutput"
          type:
            - array
            - "null"
        voice_id:
          type: string
      type: object
    CashAmount:
      additionalProperties: false
      properties:
        amount_minor:
          description: USD amount in integer minor units (cents).
          format: int64
          minimum: 0
          type: integer
        currency:
          enum:
            - USD
          type: string
      required:
        - currency
        - amount_minor
      type: object
    CatalogOutputBody:
      additionalProperties: false
      properties:
        entries:
          items:
            $ref: "#/components/schemas/ModelEntry"
          type:
            - array
            - "null"
        next_cursor:
          type: string
      required:
        - entries
      type: object
    Charge:
      additionalProperties: false
      properties:
        display_estimates:
          $ref: "#/components/schemas/DisplayEstimates"
          description: Non-authoritative display estimates. Only the credit amount is used for charging.
        price:
          $ref: "#/components/schemas/CreditAmount"
      required:
        - price
      type: object
    CreditAmount:
      additionalProperties: false
      properties:
        amount:
          pattern: ^(0|[1-9][0-9]*)[.][0-9]{3}$
          type: string
        unit:
          enum:
            - credit
          type: string
      required:
        - unit
        - amount
      type: object
    CustomerBillingPrice:
      additionalProperties: false
      properties:
        charged:
          description: "Credits consumed by this task. Set when billing_status is settled: the actual usage the model reported at the fixed rate, which may be above or below estimated; any unused part of the hold returns to the balance, and usage above the hold is charged too. 0.000 in every other state, including after a refund."
          type: string
        estimated:
          description: The estimated cost of this task, in Credits, fixed when the task was accepted. This is the amount held for the task. The charge follows actual usage and may differ slightly from it, above or below.
          type: string
        refunded:
          description: "Credits a refund returned to the balance: what this task had been charged. 0.000 unless billing_status is refunded. Absent from events created before this field was added."
          type: string
        reserved:
          description: Credits held for this task when the event was created, as a decimal string with 3 places. Equal to estimated while billing_status is held, otherwise 0.000.
          type: string
        unit:
          description: Every amount is in Credits.
          enum:
            - credit
          type: string
      required:
        - unit
        - estimated
        - reserved
        - charged
      type: object
    CustomerGenerationEvent:
      additionalProperties: false
      properties:
        billing_status:
          description: Pending awaits funding; unfunded closed without a hold; held means Credits are held for the task; settled charges verified delivery; released returns the hold; refunded reverses previously consumed generation Credits.
          enum:
            - pending
            - unfunded
            - held
            - settled
            - released
            - refunded
          type: string
        closed_status:
          description: Immutable customer closure. Unresolved means the resolution deadline passed without confirmed delivery.
          enum:
            - succeeded
            - failed
            - canceled
            - unresolved
          type: string
        created_at:
          format: date-time
          type: string
        delivery_status:
          description: Managed output delivery state, independent of supplier execution.
          enum:
            - pending
            - copying
            - ready
            - failed
          type: string
        error_code:
          description: Stable accepted-task failure code, matching generation error.code. Omitted when no failure code applies. Funding or recovery refusals, provider capacity, content policy, media validity, draft expiry and other execution failures remain distinct.
          enum:
            - insufficient_balance
            - balance_negative
            - budget_exceeded
            - spending_blocked
            - recovery_review
            - provider_unavailable
            - input_moderated
            - output_moderated
            - input_media_invalid
            - input_media_unreachable
            - draft_expired
            - input_rejected
            - generation_failed
          type: string
        event_id:
          type: string
        execution_status:
          description: "Supplier execution state: processing until execution ends. Succeeded can precede verified media delivery."
          enum:
            - processing
            - succeeded
            - failed
            - canceled
            - unresolved
          type: string
        free:
          type: boolean
        late_result_available:
          type: boolean
        price:
          $ref: "#/components/schemas/CustomerBillingPrice"
        result:
          anyOf:
            - $ref: "#/components/schemas/CustomerGenerationEventResultStruct"
            - type: "null"
        task_id:
          type: string
        type:
          enum:
            - generation.succeeded
            - generation.failed
            - generation.canceled
            - generation.unresolved
            - generation.refunded
            - generation.late_result_available
          type: string
        version:
          format: int64
          type: integer
      required:
        - price
        - event_id
        - type
        - created_at
        - task_id
        - version
        - execution_status
        - delivery_status
        - billing_status
        - closed_status
        - late_result_available
        - free
        - result
      type: object
    CustomerGenerationEventResultStruct:
      additionalProperties: false
      properties:
        asset_id:
          type: string
      required:
        - asset_id
      type: object
    CustomerWebhookTest:
      additionalProperties: false
      properties:
        created_at:
          format: date-time
          type: string
        event_id:
          type: string
        test:
          type: boolean
        type:
          enum:
            - webhook.test
          type: string
      required:
        - event_id
        - type
        - created_at
        - test
      type: object
    DeliveredOutput:
      additionalProperties: false
      properties:
        asset_id:
          type: string
        content_type:
          type: string
        index:
          format: int64
          type: integer
      required:
        - index
        - asset_id
        - content_type
      type: object
    DisplayEstimate:
      additionalProperties: false
      properties:
        amount:
          pattern: ^(0|[1-9][0-9]*)([.][0-9]+)?$
          type: string
        as_of:
          format: date-time
          type: string
        basis:
          enum:
            - current_standard_pack
          type: string
        status:
          description: Available when a current USD reference pack supplies the estimate; unavailable when no valid reference exists. This is a display estimate, not the charge.
          enum:
            - available
            - unavailable
          type: string
        tax_included:
          enum:
            - false
          type: boolean
      required:
        - status
        - tax_included
      type: object
    DisplayEstimates:
      additionalProperties: false
      properties:
        usd:
          $ref: "#/components/schemas/DisplayEstimate"
      required:
        - usd
      type: object
    Download:
      additionalProperties: false
      properties:
        url:
          type: string
        url_expires_at:
          format: date-time
          type: string
      required:
        - url
        - url_expires_at
      type: object
    Entry:
      additionalProperties: false
      properties:
        created_at:
          format: date-time
          type: string
        credits:
          type: string
        from:
          type: string
        id:
          type: string
        reference:
          type: string
        task_id:
          description: The generation this entry belongs to, for a hold, settlement, returned unused hold, release or refund of a task. Absent for entries that belong to no generation, such as top-ups.
          type: string
        to:
          type: string
      required:
        - id
        - reference
        - from
        - to
        - credits
        - created_at
      type: object
    ErrorDetail:
      additionalProperties: false
      properties:
        code:
          description: Stable request error code. invalid_input rejects the request schema; invalid_credentials/scope_denied reject authentication/authorization; ip_not_allowed/model_not_allowed reject API key IP/model restrictions; resource_not_found hides missing or inaccessible resources; conflict rejects incompatible state; insufficient_balance/budget_exceeded/spending_blocked reject funding; balance_negative (402) refuses new tasks while the organization owes Credits from a charge above its hold, until a top-up repays them; rate_limited/concurrency_limited ask for a later retry; temporarily_unavailable is transient service capacity; request_failed covers other HTTP failures. tier_not_sold, draft_not_found, draft_expired and input_duration_out_of_range reject model-specific input. input_media_invalid rejects a detected format/type mismatch; input_media_too_large rejects a probed byte size above the model limit. storage_quota_exceeded rejects an upload when the organization's storage is full. See errors for field-level details.
          enum:
            - invalid_input
            - invalid_credentials
            - insufficient_balance
            - balance_negative
            - scope_denied
            - resource_not_found
            - conflict
            - rate_limited
            - concurrency_limited
            - temporarily_unavailable
            - request_failed
            - ip_not_allowed
            - model_not_allowed
            - tier_not_sold
            - draft_not_found
            - draft_expired
            - input_duration_out_of_range
            - input_media_invalid
            - input_media_too_large
            - budget_exceeded
            - spending_blocked
            - storage_quota_exceeded
          type: string
        errors:
          items:
            $ref: "#/components/schemas/FieldError"
          type:
            - array
            - "null"
        message:
          type: string
        request_id:
          type: string
        retryable:
          type: boolean
        task_id:
          type: string
      required:
        - code
        - message
        - retryable
        - request_id
      type: object
    EstimateAmount:
      additionalProperties: false
      properties:
        credits:
          description: The Credits a create with the same body would hold.
          type: string
        usd:
          $ref: "#/components/schemas/DisplayEstimate"
      required:
        - credits
        - usd
      type: object
    EstimateBasis:
      additionalProperties: false
      properties:
        auto:
          description: The model chooses the length (for example duration -1 or an inferred video task), so the hold covers the longest output the tier allows or, for an edit whose source was measured, the source length (capped by the tier).
          type: boolean
        billed_seconds:
          description: "Per-second models only: seconds billed after the tier's minimum billing rule. 0 on per-image models."
          format: int64
          type: integer
        input_images:
          description: "Per-image models only: input images counted for the price. Always 0 on per-second (video) models, whatever images the input has."
          format: int64
          type: integer
        input_seconds:
          description: "Per-second models only: input video seconds priced, on a tier that bills input video. 0 otherwise."
          format: int64
          type: integer
        large:
          description: "Per-image models only: the large-image surcharge applies. Always false on per-second models."
          type: boolean
        output_seconds:
          description: "Per-second models only: output seconds priced. 0 on per-image models."
          format: int64
          type: integer
        outputs:
          description: "Per-image models only: output images priced. Always 0 on per-second (video) models."
          format: int64
          type: integer
      required:
        - output_seconds
        - input_seconds
        - billed_seconds
        - outputs
        - input_images
        - large
        - auto
      type: object
    EstimateResult:
      additionalProperties: false
      properties:
        basis:
          $ref: "#/components/schemas/EstimateBasis"
        estimate:
          $ref: "#/components/schemas/EstimateAmount"
      required:
        - estimate
        - basis
      type: object
    FAQ:
      additionalProperties: false
      properties:
        a:
          type: string
        q:
          type: string
      required:
        - q
        - a
      type: object
    FieldError:
      additionalProperties: false
      properties:
        path:
          type: string
        rule:
          type: string
      required:
        - path
        - rule
      type: object
    GenerationError:
      additionalProperties: false
      properties:
        code:
          description: "Funding: insufficient_balance, balance_negative (Credits were owed when the task came to be funded), budget_exceeded or spending_blocked; recovery_review when recovery closes an unfunded task for manual reconciliation. Provider: provider_unavailable after capacity/recovery exhaustion; input/output_moderated for safety refusal; input_media_invalid or input_media_unreachable for media refusal; draft_expired for an expired draft; input_rejected for unsupported input; delivery_failed when the provider succeeded but the output could not be stored; generation_failed for other terminal provider failures. Failed tasks release their customer hold."
          enum:
            - insufficient_balance
            - balance_negative
            - budget_exceeded
            - spending_blocked
            - recovery_review
            - provider_unavailable
            - input_moderated
            - output_moderated
            - input_media_invalid
            - input_media_unreachable
            - draft_expired
            - input_rejected
            - delivery_failed
            - generation_failed
          type: string
      required:
        - code
      type: object
    GenerationPage:
      additionalProperties: false
      properties:
        entries:
          items:
            $ref: "#/components/schemas/View"
          type:
            - array
            - "null"
        next_cursor:
          type: string
      required:
        - entries
      type: object
    Locale:
      additionalProperties: false
      properties:
        code:
          type: string
        label:
          type: string
        urlPrefix:
          type: string
      required:
        - code
        - label
        - urlPrefix
      type: object
    Metadata:
      additionalProperties: false
      properties:
        mime:
          type: string
        sha256:
          type: string
        size_bytes:
          format: int64
          type: integer
      required:
        - size_bytes
        - sha256
        - mime
      type: object
    ModelEntry:
      additionalProperties: false
      properties:
        asOf:
          format: date-time
          type: string
        features:
          items:
            type: string
          type:
            - array
            - "null"
        inputSchema: {}
        mediaType:
          type: string
        modelId:
          type: string
        tiers:
          items:
            $ref: "#/components/schemas/TierEntry"
          type:
            - array
            - "null"
      required:
        - modelId
        - mediaType
        - inputSchema
        - features
        - tiers
        - asOf
      type: object
    ModelPage:
      additionalProperties: false
      properties:
        descriptionMd:
          type: string
        faq:
          items:
            $ref: "#/components/schemas/FAQ"
          type:
            - array
            - "null"
        featured:
          type: boolean
        locale:
          type: string
        modelId:
          type: string
        revision:
          format: int64
          type: integer
        samples:
          items:
            $ref: "#/components/schemas/Sample"
          type:
            - array
            - "null"
        sortOrder:
          format: int64
          type: integer
        summary:
          type: string
      required:
        - modelId
        - locale
        - revision
        - summary
        - descriptionMd
        - samples
        - faq
        - sortOrder
        - featured
      type: object
    OfficialRate:
      additionalProperties: false
      properties:
        amount:
          type: string
        asOf:
          type: string
        components:
          items:
            $ref: "#/components/schemas/RateComponent"
          type:
            - array
            - "null"
        currency:
          type: string
        officialListUrl:
          type: string
        taxBasis:
          type: string
        unit:
          type: string
      required:
        - officialListUrl
        - asOf
      type: object
    OutputMetadata:
      additionalProperties: false
      properties:
        duration:
          format: int64
          type: integer
        frames:
          format: int64
          type: integer
        framespersecond:
          format: int64
          type: integer
        generate_audio:
          type: boolean
        ratio:
          type: string
        resolution:
          type: string
        seed:
          format: int64
          type: integer
      type: object
    Page:
      additionalProperties: false
      properties:
        items:
          items:
            $ref: "#/components/schemas/Entry"
          type:
            - array
            - "null"
        next_cursor:
          type: string
        tasks:
          description: One total per generation named on this page, computed over all of its transfers, including those on other pages. Use it for a task's net change and state instead of summing the loaded entries.
          items:
            $ref: "#/components/schemas/TaskTotal"
          type:
            - array
            - "null"
      required:
        - items
      type: object
    PageInfo:
      additionalProperties: false
      properties:
        next_cursor:
          type: string
      type: object
    Price:
      additionalProperties: false
      properties:
        charged:
          description: "Credits consumed by this task. Set when billing_status is settled: the actual usage the model reported at the fixed rate, which may be above or below estimated; any unused part of the hold returns to the balance, and usage above the hold is charged too. 0.000 in every other state, including after a refund."
          type: string
        estimated:
          description: The estimated cost of this task, in Credits, fixed when the task was accepted. This is the amount held for the task. The charge follows actual usage and may differ slightly from it, above or below.
          type: string
        refunded:
          description: "Credits a refund returned to the balance: what this task had been charged. 0.000 unless billing_status is refunded."
          type: string
        reserved:
          description: Credits held for this task right now, as a decimal string with 3 places. Equal to estimated while billing_status is held, otherwise 0.000.
          type: string
        unit:
          description: Every amount is in Credits.
          enum:
            - credit
          type: string
      required:
        - reserved
        - unit
        - estimated
        - charged
        - refunded
      type: object
    PriceChange:
      additionalProperties: false
      properties:
        publishedAt:
          format: date-time
          type: string
        rows:
          items:
            $ref: "#/components/schemas/PriceChangeRow"
          type:
            - array
            - "null"
        version:
          type: string
      required:
        - version
        - publishedAt
        - rows
      type: object
    PriceChangeRow:
      additionalProperties: false
      properties:
        modelId:
          type: string
        newCredits:
          type:
            - string
            - "null"
        oldCredits:
          type:
            - string
            - "null"
        tier:
          type: string
      required:
        - modelId
        - tier
        - oldCredits
        - newCredits
      type: object
    PriceComparison:
      additionalProperties: false
      properties:
        official:
          $ref: "#/components/schemas/OfficialRate"
        officialRequestAmount:
          type: string
        ourAmount:
          type: string
        referencePack:
          $ref: "#/components/schemas/ReferencePack"
        savingsPercent:
          type: string
      required:
        - official
      type: object
    PublicImagePrice:
      additionalProperties: false
      properties:
        extra_input_credits:
          type: string
        free_input_images:
          format: int64
          type: integer
        large_credits:
          type: string
        max_outputs:
          format: int64
          type: integer
        output_credits:
          type: string
      required:
        - output_credits
        - free_input_images
        - max_outputs
      type: object
    PublicPack:
      additionalProperties: false
      properties:
        bonusCredits:
          type: string
        currency:
          enum:
            - USD
          type: string
        packId:
          type: string
        principalMinor:
          format: int64
          type: integer
        purchasedCredits:
          type: string
        version:
          type: string
      required:
        - packId
        - currency
        - version
        - principalMinor
        - purchasedCredits
        - bonusCredits
      type: object
    PublicRate:
      additionalProperties: false
      properties:
        auto_duration:
          type: boolean
        counts_input:
          type: boolean
        credits_per_second:
          type: string
        max_input_seconds:
          format: int64
          type: integer
        max_seconds:
          format: int64
          type: integer
        min_seconds:
          format: int64
          type: integer
      required:
        - credits_per_second
        - min_seconds
        - max_seconds
        - max_input_seconds
        - auto_duration
        - counts_input
      type: object
    RateComponent:
      additionalProperties: false
      properties:
        condition:
          type: string
        currency:
          type: string
        maxAmount:
          type: string
        minAmount:
          type: string
        name:
          type: string
        taxBasis:
          type: string
        unit:
          type: string
      required:
        - name
        - minAmount
        - maxAmount
        - currency
        - unit
        - taxBasis
        - condition
      type: object
    ReferencePack:
      additionalProperties: false
      properties:
        currency:
          type: string
        id:
          type: string
        principalMinor:
          type: string
        purchasedUnits:
          type: string
        taxBasis:
          type: string
        version:
          type: string
      required:
        - id
        - version
        - currency
        - principalMinor
        - purchasedUnits
        - taxBasis
      type: object
    Request:
      additionalProperties: false
      properties:
        input:
          description: The model input. Its schema is the model's inputSchema in the catalog.
          type: object
        metadata:
          additionalProperties:
            type: string
          type: object
        model:
          minLength: 1
          type: string
        webhook_endpoint_id:
          type: string
      required:
        - model
        - input
      type: object
    Sample:
      additionalProperties: false
      properties:
        credits:
          type: string
        kind:
          enum:
            - video
            - image
            - audio
          type: string
        mediaUrl:
          type: string
        posterUrl:
          type: string
        prompt:
          type: string
        spec:
          type: string
      required:
        - kind
        - mediaUrl
        - prompt
        - spec
      type: object
    SiteExport:
      additionalProperties: false
      properties:
        catalogUrl:
          type: string
        catalogVersion:
          type: string
        formatVersion:
          format: int64
          type: integer
        generatedAt:
          format: date-time
          type: string
        locales:
          items:
            $ref: "#/components/schemas/Locale"
          type:
            - array
            - "null"
        modelPages:
          additionalProperties:
            additionalProperties:
              $ref: "#/components/schemas/ModelPage"
            type: object
          type: object
        packs:
          items:
            $ref: "#/components/schemas/PublicPack"
          type:
            - array
            - "null"
        priceChanges:
          items:
            $ref: "#/components/schemas/PriceChange"
          type:
            - array
            - "null"
        referencePacks:
          additionalProperties:
            $ref: "#/components/schemas/SiteReferencePack"
          type: object
      required:
        - formatVersion
        - generatedAt
        - catalogVersion
        - catalogUrl
        - locales
        - packs
        - referencePacks
        - modelPages
        - priceChanges
      type: object
    SiteReferencePack:
      additionalProperties: false
      properties:
        packId:
          type: string
        version:
          type: string
      required:
        - packId
        - version
      type: object
    TaskTotal:
      additionalProperties: false
      properties:
        net:
          description: "The net change the task made to the available balance over all its transfers, as a signed decimal: negative when Credits left it."
          type: string
        state:
          description: "Where the trail ended: held (still reserved), charged (some or all of the hold was charged), released (nothing charged; the hold came back) or refunded (the charge was reversed)."
          enum:
            - held
            - charged
            - released
            - refunded
          type: string
        task_id:
          type: string
        transfers:
          description: How many transfers the task has in total. Fewer on the loaded pages means its trail continues on earlier pages.
          format: int64
          type: integer
      required:
        - task_id
        - net
        - state
        - transfers
      type: object
    TierEntry:
      additionalProperties: false
      properties:
        id:
          type: string
        match:
          additionalProperties: {}
          type: object
        pricing:
          $ref: "#/components/schemas/TierPricing"
      required:
        - id
        - match
        - pricing
      type: object
    TierPricing:
      additionalProperties: false
      properties:
        comparison:
          $ref: "#/components/schemas/PriceComparison"
        credits:
          type: string
        image:
          $ref: "#/components/schemas/PublicImagePrice"
        kind:
          type: string
        rate:
          $ref: "#/components/schemas/PublicRate"
        usd:
          $ref: "#/components/schemas/DisplayEstimate"
      required:
        - kind
        - credits
        - usd
      type: object
    Upload:
      additionalProperties: false
      properties:
        asset_id:
          type: string
        upload_url:
          type: string
        url_expires_at:
          format: date-time
          type: string
      required:
        - asset_id
        - upload_url
        - url_expires_at
      type: object
    UploadRequest:
      additionalProperties: false
      properties:
        max_bytes:
          format: int64
          maximum: 20000000
          minimum: 1
          type: integer
        mime:
          enum:
            - image/png
            - image/jpeg
            - image/webp
            - video/mp4
            - audio/mpeg
            - audio/wav
          type: string
        purpose:
          default: generation
          description: support uploads attach to a support report and can never be used as generation input.
          enum:
            - generation
            - support
          type: string
      required:
        - mime
        - max_bytes
      type: object
    View:
      additionalProperties: false
      properties:
        allowed_actions:
          items:
            type: string
          type:
            - array
            - "null"
        billing_closed_at:
          description: When the hold was settled or released; absent while Credits are still held.
          format: date-time
          type: string
        billing_status:
          description: Pending awaits funding; unfunded closed without a hold; held means Credits are held for the task; settled charges verified delivery at the existing pricing rules; released returns the hold after failure, cancellation, timeout or zero-charge delivery; refunded reverses previously consumed generation Credits.
          enum:
            - pending
            - unfunded
            - held
            - settled
            - released
            - refunded
          type: string
        closed_at:
          format: date-time
          type:
            - string
            - "null"
        created_at:
          description: When the generation was accepted. Lists are ordered by this time, newest first.
          format: date-time
          type: string
        customer_resolution_deadline:
          format: date-time
          type: string
        delivery_status:
          description: "Output delivery: pending before upstream success; copying into managed storage; ready after verified delivery; failed when delivery cannot complete."
          enum:
            - pending
            - copying
            - ready
            - failed
          type: string
        error:
          anyOf:
            - $ref: "#/components/schemas/GenerationError"
            - type: "null"
        execution_status:
          description: "Supplier execution state, separate from delivery and billing: processing until execution ends. Succeeded means upstream execution finished, not that output delivery is ready."
          enum:
            - processing
            - succeeded
            - failed
            - canceled
            - unresolved
          type: string
        held_at:
          description: When Credits were held for the task; absent while it awaits funding or when it closed unfunded.
          format: date-time
          type: string
        id:
          type: string
        input:
          description: "The model input as accepted, after normalization, with media as sent: asset ids or your own URLs. Returned when reading a single task; list entries omit it."
        key_id:
          description: API key that created the task; empty for console tasks.
          type: string
        key_name:
          type: string
        late_result_available:
          type: boolean
        metadata:
          additionalProperties:
            type: string
          type: object
        model:
          description: Public model id the generation was created with.
          type: string
        price:
          $ref: "#/components/schemas/Price"
        queue_ms:
          description: Milliseconds from acceptance to first dispatch.
          format: int64
          type: integer
        result:
          anyOf:
            - $ref: "#/components/schemas/Asset"
            - type: "null"
        run_ms:
          description: Milliseconds from first dispatch to close.
          format: int64
          type: integer
        source:
          description: "Where the generation was created: api (API key) or console (signed-in session)."
          enum:
            - api
            - console
          type: string
        started_at:
          description: When the task was first dispatched to run.
          format: date-time
          type: string
        status:
          description: processing from acceptance until the task closes, including while it awaits funding and while outputs are copied; succeeded has delivered outputs; failed, canceled and unresolved are closed. Canceled is set by the system only, for example when a task is not funded or not started in time. Unresolved closes after the resolution deadline. A late result may still arrive without a new charge.
          enum:
            - processing
            - succeeded
            - failed
            - canceled
            - unresolved
          type: string
        version:
          format: int64
          type: integer
      required:
        - id
        - status
        - execution_status
        - delivery_status
        - billing_status
        - version
        - price
        - allowed_actions
        - customer_resolution_deadline
        - created_at
        - closed_at
        - model
        - source
        - late_result_available
        - error
        - result
      type: object
    Wallet:
      additionalProperties: false
      properties:
        available:
          type: string
        balance:
          description: Spendable Credits minus owed, as a signed decimal. Spendable excludes Credits frozen for review, which stay in available but cannot be spent or repay owed Credits, so balance is negative exactly while Credits are owed.
          type: string
        has_purchased:
          description: True once any purchase, including an auto top-up, has been credited to this organization, whatever the balance is now. Promotional, trial and compensation Credits do not count.
          type: boolean
        held:
          type: string
        owed:
          description: "Credits owed: the part of a task's actual charge above its hold that the balance could not pay. A top-up repays it first. While it is above zero, new tasks are refused with balance_negative."
          type: string
        paid_available:
          type: string
        promotional_available:
          type: string
        refund_reserved:
          type: string
        total:
          type: string
        unit:
          enum:
            - credit
          type: string
      required:
        - unit
        - available
        - held
        - refund_reserved
        - total
        - paid_available
        - promotional_available
        - owed
        - balance
      type: object
  securitySchemes:
    bearerAuth:
      scheme: bearer
      type: http
info:
  title: VizoAPI
  version: v1
openapi: 3.1.0
paths:
  /site/v1/export.json:
    get:
      operationId: getSiteExport
      parameters:
        - in: header
          name: If-None-Match
          schema:
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SiteExport"
          description: OK
          headers:
            Cache-Control:
              schema:
                type: string
            ETag:
              schema:
                type: string
        "304":
          description: The export matches If-None-Match.
        "422":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unprocessable Entity
        "500":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Internal Server Error
        "503":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Service Unavailable
      tags:
        - Site
  /v1/assets/uploads:
    post:
      operationId: createAssetUpload
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/UploadRequest"
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Upload"
          description: OK
        "401":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unauthorized
        "403":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Forbidden
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Not Found
        "409":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Conflict
        "422":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unprocessable Entity
        "500":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Internal Server Error
        "503":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Service Unavailable
      security:
        - bearerAuth: []
      tags:
        - Assets
  /v1/assets/{id}:
    delete:
      operationId: deleteAsset
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        "202":
          description: Accepted
        "401":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unauthorized
        "403":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Forbidden
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Not Found
        "409":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Conflict
        "422":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unprocessable Entity
        "500":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Internal Server Error
        "503":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Service Unavailable
      security:
        - bearerAuth: []
      tags:
        - Assets
  /v1/assets/{id}/complete:
    post:
      operationId: completeAssetUpload
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Metadata"
          description: OK
        "401":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unauthorized
        "403":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Forbidden
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Not Found
        "409":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Conflict
        "422":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unprocessable Entity
        "500":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Internal Server Error
        "503":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Service Unavailable
      security:
        - bearerAuth: []
      tags:
        - Assets
  /v1/assets/{id}/download:
    get:
      operationId: downloadAsset
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Download"
          description: OK
        "401":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unauthorized
        "403":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Forbidden
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Not Found
        "409":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Conflict
        "422":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unprocessable Entity
        "500":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Internal Server Error
        "503":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Service Unavailable
      security:
        - bearerAuth: []
      tags:
        - Assets
  /v1/estimates:
    post:
      description: "Prices a create body without creating a generation or holding Credits. The body is the same as createGeneration; webhook_endpoint_id and metadata are accepted and ignored. The input and its media are checked and priced exactly as a create would, including measuring a public input video, so a body the estimate refuses gets the same input error from createGeneration. A create can still fail where an estimate succeeds: on funding or budget (402, 403), on the rate and concurrency limits (429) or on a route change (409). An estimate that must measure an input video takes one token from the organization's generation rate limit and answers 429 rate_limited with Retry-After when none is left; other estimates take one token from the organization's generation read limit and answer 429 rate_limited with Retry-After when none is left. Prices can change between an estimate and a create."
      operationId: createEstimate
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Request"
        required: true
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EstimateResult"
          description: OK
        "401":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unauthorized
        "403":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Forbidden
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Not Found
        "422":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unprocessable Entity
        "429":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Too Many Requests
        "500":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Internal Server Error
        "503":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Service Unavailable
      security:
        - bearerAuth: []
      summary: Estimate the Credits a generation would hold
      tags:
        - Models
  /v1/generations:
    get:
      description: Lists the project's generations newest first (by created_at, then id). Pass next_cursor as cursor for the next page. Filters combine; created_after is inclusive and created_before exclusive.
      operationId: listGenerations
      parameters:
        - explode: false
          in: query
          name: limit
          schema:
            default: 50
            format: int64
            maximum: 100
            minimum: 1
            type: integer
        - explode: false
          in: query
          name: client_reference
          schema:
            maxLength: 256
            type: string
        - explode: false
          in: query
          name: cursor
          schema:
            maxLength: 64
            type: string
        - description: Only generations created with this public model id.
          explode: false
          in: query
          name: model
          schema:
            description: Only generations created with this public model id.
            maxLength: 128
            type: string
        - description: Only generations created through the API or the console.
          explode: false
          in: query
          name: source
          schema:
            description: Only generations created through the API or the console.
            enum:
              - api
              - console
            type: string
        - description: Only generations whose status currently equals this value. processing matches every unfinished task.
          explode: false
          in: query
          name: status
          schema:
            description: Only generations whose status currently equals this value. processing matches every unfinished task.
            enum:
              - processing
              - succeeded
              - failed
              - canceled
              - unresolved
            pattern: ^[a-z_]{1,32}$
            type: string
        - description: RFC 3339 time. Only generations created at or after it.
          explode: false
          in: query
          name: created_after
          schema:
            description: RFC 3339 time. Only generations created at or after it.
            format: date-time
            type: string
        - description: RFC 3339 time. Only generations created before it.
          explode: false
          in: query
          name: created_before
          schema:
            description: RFC 3339 time. Only generations created before it.
            format: date-time
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/GenerationPage"
          description: OK
        "401":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unauthorized
        "402":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Payment Required
        "403":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Forbidden
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Not Found
        "409":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Conflict
        "422":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unprocessable Entity
        "429":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Too Many Requests
        "500":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Internal Server Error
        "503":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Service Unavailable
      security:
        - bearerAuth: []
      tags:
        - Generations
    post:
      description: Each accepted POST durably records a separate generation. The response has status processing and billing_status pending; the reserved amount is zero until Credits are held. A funding rejection closes the task with error.code set; read it again to see it. Submitting the same request twice can incur two charges. After a lost response, check the generation list before deciding to create another task. HTTP 429 with code concurrency_limited means the organization already has as many unfinished tasks of this media type (video, image, audio or other) as its concurrency limit allows (by default 3 video, 10 image and 10 audio tasks at once per organization; see /docs/rate-limits); nothing is recorded or held, so retry after the Retry-After seconds or queue on your side. Other 429 answers use rate_limited.
      operationId: createGeneration
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Request"
        required: true
      responses:
        "202":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/View"
          description: Accepted
        "401":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unauthorized
        "402":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Payment Required
        "403":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Forbidden
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Not Found
        "409":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Conflict
        "422":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unprocessable Entity
        "429":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: "Too many requests. Code concurrency_limited: the organization already has as many unfinished tasks of this media type as its concurrency limit allows, by default 3 video tasks at once per organization (see /docs/rate-limits); nothing is recorded or held. Code rate_limited: the per-minute rate or the queued-task backlog is full. Retry after Retry-After seconds."
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                minimum: 1
                type: integer
        "500":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Internal Server Error
        "503":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Service Unavailable
      security:
        - bearerAuth: []
      tags:
        - Generations
  /v1/generations/{id}:
    get:
      operationId: getGeneration
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/View"
          description: OK
        "401":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unauthorized
        "402":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Payment Required
        "403":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Forbidden
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Not Found
        "409":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Conflict
        "422":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unprocessable Entity
        "429":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Too Many Requests
        "500":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Internal Server Error
        "503":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Service Unavailable
      security:
        - bearerAuth: []
      tags:
        - Generations
  /v1/ledger:
    get:
      operationId: listLedger
      parameters:
        - explode: false
          in: query
          name: cursor
          schema:
            maxLength: 19
            type: string
        - explode: false
          in: query
          name: limit
          schema:
            default: 50
            format: int64
            maximum: 100
            minimum: 1
            type: integer
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Page"
          description: OK
        "400":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Bad Request
        "401":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unauthorized
        "403":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Forbidden
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Not Found
        "409":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Conflict
        "422":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unprocessable Entity
        "429":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Too Many Requests
        "500":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Internal Server Error
        "503":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Service Unavailable
      security:
        - bearerAuth: []
      summary: listLedger
      tags:
        - Billing
  /v1/models:
    get:
      operationId: listModels
      parameters:
        - explode: false
          in: query
          name: limit
          schema:
            default: 50
            format: int64
            maximum: 100
            minimum: 1
            type: integer
        - description: The last model id of the previous page.
          explode: false
          in: query
          name: cursor
          schema:
            description: The last model id of the previous page.
            maxLength: 64
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CatalogOutputBody"
          description: OK
        "401":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unauthorized
        "403":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Forbidden
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Not Found
        "422":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unprocessable Entity
        "500":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Internal Server Error
        "503":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Service Unavailable
      security:
        - bearerAuth: []
      summary: List accessible model specifications
      tags:
        - Models
  /v1/models/{id}:
    get:
      operationId: getModel
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CatalogOutputBody"
          description: OK
        "401":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unauthorized
        "403":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Forbidden
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Not Found
        "422":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unprocessable Entity
        "500":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Internal Server Error
        "503":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Service Unavailable
      security:
        - bearerAuth: []
      summary: Read accessible specifications for one model
      tags:
        - Models
  /v1/wallet:
    get:
      description: The organization's Credits balance. A billing key needs the billing:read scope; a project key needs balance:read and reads the balance of the organization its project belongs to.
      operationId: getWallet
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Wallet"
          description: OK
        "400":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Bad Request
        "401":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unauthorized
        "403":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Forbidden
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Not Found
        "409":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Conflict
        "422":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Unprocessable Entity
        "429":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Too Many Requests
        "500":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Internal Server Error
        "503":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/APIError"
          description: Service Unavailable
      security:
        - bearerAuth: []
      summary: getWallet
      tags:
        - Billing
webhooks:
  generationEvent:
    post:
      description: "Signed per the Standard Webhooks specification. Verify with an official Standard Webhooks library and the endpoint's whsec_ signing secret: it checks Base64(HMAC-SHA256(Base64-decoded secret, webhook-id + '.' + webhook-timestamp + '.' + raw_body)) against each v1 entry in webhook-signature in constant time and rejects timestamps more than five minutes from now. Deduplicate by webhook-id. Redelivery preserves the body and webhook-id and signs again with a new timestamp."
      operationId: generationEvent
      parameters:
        - description: Unique event ID, equal to event_id in the body. Unchanged on retries and redelivery; use it to deduplicate.
          in: header
          name: webhook-id
          required: true
          schema:
            type: string
        - description: Unix time in seconds when this attempt was sent.
          in: header
          name: webhook-timestamp
          required: true
          schema:
            type: string
        - description: Space-delimited list of v1 signatures. Two are sent for 24 hours after a secret rotation; accept the request if any one matches.
          in: header
          name: webhook-signature
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CustomerGenerationEvent"
        required: true
      responses:
        2XX:
          description: Delivery accepted
  webhookTest:
    post:
      description: "Signed per the Standard Webhooks specification. Verify with an official Standard Webhooks library and the endpoint's whsec_ signing secret: it checks Base64(HMAC-SHA256(Base64-decoded secret, webhook-id + '.' + webhook-timestamp + '.' + raw_body)) against each v1 entry in webhook-signature in constant time and rejects timestamps more than five minutes from now. Deduplicate by webhook-id. Redelivery preserves the body and webhook-id and signs again with a new timestamp."
      operationId: webhookTest
      parameters:
        - description: Unique event ID, equal to event_id in the body. Unchanged on retries and redelivery; use it to deduplicate.
          in: header
          name: webhook-id
          required: true
          schema:
            type: string
        - description: Unix time in seconds when this attempt was sent.
          in: header
          name: webhook-timestamp
          required: true
          schema:
            type: string
        - description: Space-delimited list of v1 signatures. Two are sent for 24 hours after a secret rotation; accept the request if any one matches.
          in: header
          name: webhook-signature
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CustomerWebhookTest"
        required: true
      responses:
        2XX:
          description: Delivery accepted
