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

# Finish an upload

> Third of the three calls. Declares that the bytes have landed and hands
the file to validation, which checks the container and codec (H.264/AVC
in MP4) and the duration.

Validation is asynchronous: the status returned here is normally
`processing`. Poll `GET /v1/videos/{video_id}` for the outcome. Calling
this on a video that is already `ready` or `failed` is harmless and
changes nothing.




## OpenAPI

````yaml /openapi/galileo-v1.yaml post /v1/videos/{video_id}/complete
openapi: 3.1.0
info:
  title: Galileo API
  version: 0.1.0
  summary: Evaluate generated videos with Galileo.
  description: |
    Submit generated videos for visual-glitch and prompt-misalignment analysis.
    Evaluation jobs run asynchronously. Retrieve a job until its status reaches
    `completed`, `partial`, or `failed`.
  contact:
    name: Physion Labs support
    email: support@physionlabs.ai
  license:
    name: Proprietary
    identifier: LicenseRef-Proprietary
servers:
  - url: https://api.physionlabs.ai
    description: Production
  - url: https://api-dev.physionlabs.ai
    description: Development
security:
  - bearerAuth: []
tags:
  - name: Platform
    description: Service health and account metadata.
  - name: Evaluations
    description: Submit videos and retrieve Galileo results.
  - name: Videos
    description: Upload a video once and reference it from evaluations.
paths:
  /v1/videos/{video_id}/complete:
    parameters:
      - $ref: '#/components/parameters/VideoId'
    post:
      tags:
        - Videos
      summary: Finish an upload
      description: |
        Third of the three calls. Declares that the bytes have landed and hands
        the file to validation, which checks the container and codec (H.264/AVC
        in MP4) and the duration.

        Validation is asynchronous: the status returned here is normally
        `processing`. Poll `GET /v1/videos/{video_id}` for the outcome. Calling
        this on a video that is already `ready` or `failed` is harmless and
        changes nothing.
      operationId: completeVideo
      responses:
        '200':
          description: Upload accepted for validation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Video'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  parameters:
    VideoId:
      name: video_id
      in: path
      required: true
      description: Video identifier, as returned by `POST /v1/videos`.
      schema:
        type: string
  schemas:
    Video:
      type: object
      required:
        - id
        - status
        - cdn_url
      properties:
        id:
          type: string
        object:
          type: string
          const: video
        status:
          $ref: '#/components/schemas/VideoStatus'
        cdn_url:
          type: string
          format: uri
        duration_sec:
          type:
            - number
            - 'null'
        width:
          type:
            - integer
            - 'null'
        height:
          type:
            - integer
            - 'null'
        size_bytes:
          type:
            - integer
            - 'null'
        created:
          type: integer
          description: Unix seconds.
    VideoStatus:
      type: string
      enum:
        - pending
        - processing
        - ready
        - failed
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          $ref: '#/components/schemas/Error'
        quota:
          $ref: '#/components/schemas/RateLimitWindow'
    Error:
      type: object
      required:
        - type
        - code
        - message
        - request_id
      properties:
        type:
          $ref: '#/components/schemas/ErrorType'
        code:
          $ref: '#/components/schemas/ErrorCode'
        message:
          type: string
        request_id:
          type: string
    RateLimitWindow:
      type: object
      required:
        - limit
        - used
        - remaining
        - reset_at
        - reset_in_sec
        - window_sec
        - unlimited
      properties:
        limit:
          type: integer
          minimum: 0
        used:
          type: integer
          minimum: 0
        remaining:
          type: integer
          minimum: 0
        reset_at:
          type:
            - integer
            - 'null'
          minimum: 0
        reset_in_sec:
          type:
            - integer
            - 'null'
          minimum: 0
        window_sec:
          type: integer
          minimum: 1
        unlimited:
          type: boolean
    ErrorType:
      type: string
      enum:
        - invalid_request_error
        - authentication_error
        - rate_limit_error
        - api_error
    ErrorCode:
      type: string
      enum:
        - invalid_body
        - unknown_model
        - missing_video
        - missing_prompt
        - prompt_too_long
        - invalid_glitch_types
        - video_too_long
        - invalid_video
        - not_found
        - not_implemented
        - insufficient_credits
        - missing_api_key
        - invalid_api_key
        - unauthenticated
        - rate_limited
        - concurrency_limit
        - internal_error
        - model_unavailable
        - model_output_invalid
        - model_timeout
        - run_abandoned
  responses:
    Unauthorized:
      description: The API key is missing, invalid, or revoked.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: The resource does not exist or is unavailable to this account.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    RateLimited:
      description: The account reached a rate or concurrency limit.
      headers:
        X-RateLimit-Limit:
          $ref: '#/components/headers/RateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/RateLimitRemaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/RateLimitReset'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalServerError:
      description: The API encountered an unexpected error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  headers:
    RateLimitLimit:
      description: Maximum submissions in the current sliding window.
      schema:
        type: integer
        minimum: 0
    RateLimitRemaining:
      description: Submissions available before the next refusal.
      schema:
        type: integer
        minimum: 0
    RateLimitReset:
      description: Unix seconds when the next rate-limit slot becomes available.
      schema:
        type: integer
        minimum: 0
    RetryAfter:
      description: Seconds to wait before retrying.
      schema:
        type: integer
        minimum: 1
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Galileo API key
      description: Use a key created in the Playground. Keys begin with `gk_`.

````