> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aihubmax.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Video Understanding

> Use the returned task ID to [query the task](/pages/en/api-manual/task-management/get-task-detail) for the final result.



## OpenAPI

````yaml openapi/en/llm-video.json POST /v1/llm/generations
openapi: 3.1.0
info:
  title: LLM · llm-video protocol
  version: '1.0'
  description: >-
    Request format of the unified LLM entrypoint **`llm-video`**: `prompt` +
    `video_urls[]` (1–10 items) → video understanding.


    **The `/v1/llm/generations` endpoint supports 5 request forms**:

    - `llm-text`: `prompt` only

    - `llm-vision`: `prompt` + `image_urls[]`

    - `llm-video` (this file): `prompt` + `video_urls[]`

    - `llm-audio`: `audio_url`

    - `llm-custom`: `messages[]` (OpenAI Chat compatible)


    **video_urls accepts URL or base64 data URI**:

    - HTTP/HTTPS URL (publicly reachable)

    - `data:video/<mp4|webm|mov>;base64,<payload>` data URI (base64 inline; note
    that video base64 payloads are large)


    **Video token cost note**: video is typically encoded by frame sampling +
    temporal encoding; a 30s clip may consume 20K+ tokens. Prefer long-context
    models like the gemini family.


    The final task result is queried via `GET /v1/tasks/{task_id}`; the SSE
    streaming subscription endpoint is `GET
    /v1/llm/generations/{task_id}/stream`, shared by all 5 protocols.
servers:
  - url: https://api.aihubmax.com
security:
  - BearerAuth: []
paths:
  /v1/llm/generations:
    post:
      tags:
        - LLM > llm-video
      summary: Submit an LLM generation task (llm-video protocol)
      description: >-
        Use the returned task ID to [query the
        task](/pages/en/api-manual/task-management/get-task-detail) for the
        final result.
      operationId: llm-video
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LLMVideoRequest'
            examples:
              example_0:
                summary: Async — describe a video
                value:
                  model: gemini-2.5-pro
                  prompt: What is happening in this video?
                  video_urls:
                    - >-
                      https://storage.googleapis.com/cloud-samples-data/video/animals.mp4
                  max_tokens: 128
              example_1:
                summary: Sync non-stream with reasoning enabled
                value:
                  model: gemini-2.5-pro
                  prompt: Identify the species and habitat in one sentence.
                  video_urls:
                    - >-
                      https://storage.googleapis.com/cloud-samples-data/video/animals.mp4
                  sync: true
                  max_tokens: 64
                  reasoning: true
      responses:
        '200':
          description: Task created (async mode) / full response (sync mode)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubmitResponse'
              examples:
                non_stream:
                  summary: sync=false, stream=false
                  value:
                    id: task-llmrouter-1776874481-rj6bs3yb
                    object: llm.generation.task
                    type: llm
                    model: gemini-2.5-pro
                    status: pending
                    progress: 0
                    created: 1776874481
                    stream: null
                    results: null
                    error: null
                stream:
                  summary: sync=false, stream=true
                  value:
                    id: task-llmrouter-1776874565-yq3szvcu
                    object: llm.generation.task
                    type: llm
                    model: gemini-2.5-pro
                    status: pending
                    progress: 0
                    created: 1776874565
                    stream:
                      url: >-
                        /v1/llm/generations/task-llmrouter-1776874565-yq3szvcu/stream
                    results: null
                    error: null
        '401':
          $ref: '#/components/responses/Unauthorized'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalServerError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  schemas:
    LLMVideoRequest:
      type: object
      required:
        - model
        - prompt
        - video_urls
      additionalProperties: true
      properties:
        model:
          type: string
          description: >-
            [Get Model
            List](/pages/en/api-manual/text-series/llm-async/llm-generations-models)
          example: gemini-2.5-pro
        prompt:
          type: string
          maxLength: 100000
          description: User prompt, up to 100,000 characters.
          example: What is happening in this video?
        video_urls:
          type: array
          minItems: 1
          maxItems: 10
          description: >-
            Array of video sources (1–10). Each element accepts one of the
            following two forms:

            - Publicly reachable HTTP/HTTPS URL

            - `data:video/<type>;base64,<payload>` data URI (base64 inline; note
            that video payloads are large)


            **URL format constraints** (based on fal openrouter testing,
            2026-05-13):

            - Direct video files: the extension must be `.mp4` / `.mpeg` /
            `.mpg` / `.mov` / `.webm`

            - YouTube videos: `https://www.youtube.com/watch?v=<id>` and
            `https://youtu.be/<id>` are supported (Gemini family only)

            - YouTube Shorts URLs (`https://www.youtube.com/shorts/<id>`) are
            **not supported**; the upstream returns 422. The client can rewrite
            `<id>` into the `watch?v=<id>` form before calling


            **Model constraints**: whether multiple videos are supported and the
            maximum count are determined by the upstream behind the selected
            model; when a model supports only a single video but the request
            passes multiple, the routing layer returns 422
            `model_rule_violation` (the specific rules are maintained in
            `app/relays/llm_router/model_rules.py`). The Gemini family generally
            supports multiple videos.


            **Cost note**: video is encoded by frame + time; a 30s clip may
            consume 20K+ tokens. Prefer short clips or low-frame-rate sources.


            **Inline base64 (asynchronous mode only, when `sync` is omitted or
            `false`)**: Base64 recognized by the gateway as inline media
            (`data:` URI, or at least 4096 encoded characters whose decoded
            content matches a known media signature) is uploaded to file storage
            and replaced with a URL before the request is persisted or submitted
            upstream; the original base64 is not stored. Shorter raw base64 or
            content with an unrecognized signature is passed through unchanged
            and is not size-validated. Limits apply only to inline base64 items
            (public HTTP(S) URLs are not limited): decoded size ≤ 5 MB per item,
            ≤ 5 inline items per array, ≤ 10 MB total per request, and ≤ 20
            inline items per request. An invalid `data:` prefix or payload that
            decodes to zero bytes returns 422; exceeding a limit also returns
            422. Use `/v1/files/upload` first and pass the resulting URL
            instead.


            When `sync: true`, the request is not stored as a task and the rules
            above do not apply: inline base64 is submitted upstream unchanged
            without size or count validation.
          items:
            type: string
          example:
            - >-
              https://storage.googleapis.com/cloud-samples-data/video/animals.mp4
        sync:
          type: boolean
          default: false
          description: Synchronous mode (see llm-text schema).
          example: false
        stream:
          type: boolean
          default: false
          description: Whether to stream (see llm-text schema).
          example: false
        max_tokens:
          type: integer
          nullable: true
          minimum: 1
          description: Generation token limit. Optional.
          example: 128
        temperature:
          type: number
          nullable: true
          minimum: 0
          maximum: 2
          description: Sampling temperature, range [0, 2]. Optional.
        system_prompt:
          type: string
          nullable: true
          maxLength: 10000
          description: System instruction. Optional.
        reasoning:
          type: boolean
          nullable: true
          description: >-
            Whether to include reasoning tokens. Thinking models like
            `gemini-2.5-pro` may require this to be set to `true`.
    SubmitResponse:
      type: object
      description: >-
        Submit response, conforming to the unified task standard shape.
        `results` / `error` are fixed at `null` during submit; they are returned
        via `GET /v1/tasks/{task_id}` after the task completes or fails. In
        `sync=true, stream=false` mode, the endpoint directly returns the full
        OpenAI ChatCompletion JSON.
      required:
        - id
        - object
        - type
        - model
        - status
        - progress
        - created
      properties:
        id:
          type: string
          description: Task ID, formatted as `task-llmrouter-{timestamp}-{8random}`.
          example: task-llmrouter-1776874565-yq3szvcu
        object:
          type: string
          enum:
            - llm.generation.task
          example: llm.generation.task
        type:
          type: string
          enum:
            - llm
          example: llm
        model:
          type: string
          description: The model name submitted by the client (echoed verbatim)
          example: gemini-2.5-pro
        status:
          type: string
          enum:
            - pending
          example: pending
        progress:
          type: integer
          example: 0
        created:
          type: integer
          example: 1776874565
        stream:
          nullable: true
          description: 'Returns `{url: ...}` when `stream=true`; `null` when `stream=false`.'
          oneOf:
            - $ref: '#/components/schemas/StreamInfo'
            - type: 'null'
        results:
          type: array
          nullable: true
          description: >-
            Fixed at `null` during submit; returned via `GET
            /v1/tasks/{task_id}` after the task completes — `results[0]` is the
            full OpenAI `ChatCompletion` response.
          items:
            type: object
          example: null
        error:
          type: object
          nullable: true
          description: >-
            Fixed at `null` during submit; returned via `GET
            /v1/tasks/{task_id}` when the task fails.
          example: null
    StreamInfo:
      type: object
      required:
        - url
      properties:
        url:
          type: string
          example: /v1/llm/generations/task-llmrouter-1776874565-yq3szvcu/stream
    ErrorResponse401:
      type: object
      properties:
        error:
          type: object
          properties:
            message:
              type: string
              example: No authentication token provided
            type:
              type: string
              example: authentication_error
    ErrorResponse422:
      type: object
      description: >-
        Parameter validation failure. Common `code`s: `model_rule_violation`
        (hit a model's inherent rule, e.g. a single-video model received
        multiple), `model_not_support_capability` (no candidate channel declares
        the `video` capability), `model_not_registered`, `invalid_param`,
        `upstream_client_error`.
      properties:
        error:
          type: object
          properties:
            message:
              type: string
              example: >-
                model 'xxx' only accepts a single video_url; received
                video_urls.length=2
            type:
              type: string
              example: invalid_request_error
            code:
              type: string
              example: model_input_not_supported
    ErrorResponse429:
      type: object
      properties:
        error:
          type: object
          properties:
            message:
              type: string
              example: Request rate limit exceeded
            type:
              type: string
              example: rate_limit_error
    ErrorResponse500:
      type: object
      properties:
        error:
          type: object
          properties:
            message:
              type: string
              example: Internal server error
            type:
              type: string
              example: internal_error
    ErrorResponse503:
      type: object
      properties:
        error:
          type: object
          properties:
            message:
              type: string
              example: 'all 3 candidates exhausted; last error: ...'
            type:
              type: string
              example: upstream_error
            code:
              type: string
              example: all_platforms_exhausted
  responses:
    Unauthorized:
      description: Token invalid or missing
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse401'
    UnprocessableEntity:
      description: >-
        Parameter validation failure / model intrinsic constraint (e.g. a
        single-video model received multiple) / no candidate channel declares
        the `video` capability / model not registered / upstream 4xx
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse422'
    TooManyRequests:
      description: Request rate limit exceeded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse429'
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse500'
    ServiceUnavailable:
      description: Upstream service unavailable
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse503'
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        All endpoints require Bearer Token authentication. Add to the request
        header:


        `Authorization: Bearer YOUR_API_KEY`


        `YOUR_API_KEY` is the API Token (`sk-...` format).

````