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

> ## Agent Instructions
> Leap's API is at https://api.tryleap.ai. Send the key in the x-api-key header or as Authorization: Bearer; keys start with leap_.
> Take model IDs and input schemas from GET /v1/models/{creator}/{name}, or from https://api.tryleap.ai/v1/public/models without a key. Never guess an input field: unknown fields are a 400.
> Model inputs take uploaded file IDs (file_...), never URLs.
> To give a coding agent the whole API, install the Leap skill: curl -fsSL https://www.tryleap.ai/install.sh | sh
> The full OpenAPI 3.1 spec is at https://www.tryleap.ai/docs/openapi.json.

# Start a video or sound upload

> The first of three steps for a video or a sound: this answers with a URL. `PUT` the file's bytes there with exactly `upload_headers` within the hour, then complete the upload. Up to 1 GB of video (MP4, MOV, WebM) or 500 MB of audio (MP3, WAV, M4A), and up to 4 hours long. Needs credit on your balance. A workspace can upload 5 GB a day, with 10 uploads in flight at once.

Needs an API key with the `generations:write` scope.



## OpenAPI

````yaml /openapi.json post /v1/uploads
openapi: 3.1.0
info:
  title: Leap API
  version: 1.0.0
  description: >-
    One API for the best image, video and audio models. Every request goes to
    `https://api.tryleap.ai` with your API key in the `x-api-key` header, or as
    `Authorization: Bearer leap_...`. Create a key at
    https://app.tryleap.ai/go/api.


    Guides, examples and the errors list are at https://www.tryleap.ai/docs.
servers:
  - url: https://api.tryleap.ai
security:
  - ApiKey: []
  - Bearer: []
tags:
  - name: Models
    description: >-
      Every model and preset you can run, with its price and the JSON Schema of
      the input it takes.
  - name: Quotes
    description: >-
      The exact price of a run before you start it, with its input checked and
      its defaults filled in.
  - name: Generations
    description: >-
      A generation is one run of a model or preset: queued, then running, then
      succeeded, failed or canceled. Only a succeeded run is charged.
  - name: Batches
    description: >-
      Up to 50 generations priced and held together in one request, each then
      run as its own generation.
  - name: Webhooks
    description: >-
      URLs your workspace's events are POSTed to, signed following Standard
      Webhooks, and the default secret for the `webhook` URL a request names.
  - name: Events
    description: >-
      What happened in your workspace, kept 30 days, with each delivery to your
      webhooks and a way to send one again.
  - name: Files
    description: >-
      Photos, videos and sounds that models take as input. Upload one, then pass
      its `file_...` ID in the input field the model's schema names.
  - name: Credits
    description: Your workspace's balance in US dollars.
externalDocs:
  url: https://www.tryleap.ai/docs
paths:
  /v1/uploads:
    post:
      tags:
        - Files
      summary: Start a video or sound upload
      description: >-
        The first of three steps for a video or a sound: this answers with a
        URL. `PUT` the file's bytes there with exactly `upload_headers` within
        the hour, then complete the upload. Up to 1 GB of video (MP4, MOV, WebM)
        or 500 MB of audio (MP3, WAV, M4A), and up to 4 hours long. Needs credit
        on your balance. A workspace can upload 5 GB a day, with 10 uploads in
        flight at once.


        Needs an API key with the `generations:write` scope.
      operationId: createUpload
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UploadRequest'
      responses:
        '201':
          description: Where and how to send the bytes.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            RateLimit-Reset:
              $ref: '#/components/headers/RateLimit-Reset'
          content:
            application/json:
              example:
                id: file_8Vb2Nc5Xm1Qz7Lk4Rt9Wd3Ph
                object: upload
                content_type: video/mp4
                bytes: 48213992
                filename: interview.mp4
                upload_url: >-
                  https://leap-media.public.blob.vercel-storage.com/media/uploads/file_8Vb2Nc5Xm1Qz7Lk4Rt9Wd3Ph
                upload_method: PUT
                upload_headers:
                  x-api-version: '11'
                  x-vercel-blob-access: private
                  x-content-type: video/mp4
                expires_at: '2026-10-04T19:20:03.441Z'
              schema:
                $ref: '#/components/schemas/Upload'
        '400':
          $ref: '#/components/responses/InvalidParameterOrConflictingCredentials'
        '401':
          $ref: '#/components/responses/AuthenticationRequired'
        '402':
          $ref: '#/components/responses/InsufficientCredit'
        '403':
          $ref: '#/components/responses/PermissionDenied'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'
components:
  schemas:
    UploadRequest:
      type: object
      properties:
        content_type:
          type: string
          enum:
            - video/mp4
            - video/quicktime
            - video/webm
            - audio/mpeg
            - audio/mp3
            - audio/wav
            - audio/x-wav
            - audio/wave
            - audio/mp4
            - audio/x-m4a
          description: 'The file''s type: MP4, MOV or WebM video; MP3, WAV or M4A audio.'
        bytes:
          type: integer
          exclusiveMinimum: 0
          maximum: 1073741824
          description: The file's exact size in bytes.
        filename:
          description: A name to keep with the file, such as `interview.mp4`.
          type: string
          minLength: 1
          maxLength: 200
      required:
        - content_type
        - bytes
      additionalProperties: false
    Upload:
      type: object
      properties:
        id:
          type: string
          description: >-
            The upload's ID, `file_...`. Completing it makes a file with the
            same ID.
        object:
          type: string
          const: upload
        content_type:
          type: string
          description: The type you declared.
        bytes:
          type: integer
          exclusiveMinimum: 0
          maximum: 9007199254740991
          description: The size you declared, in bytes.
        filename:
          description: The name you gave, if any.
          type:
            - string
            - 'null'
        upload_url:
          type: string
          description: Where to send the file's bytes.
        upload_method:
          type: string
          const: PUT
          description: The method to send them with.
        upload_headers:
          type: object
          propertyNames:
            type: string
          additionalProperties:
            type: string
          description: Headers to send with the bytes, exactly as given.
        expires_at:
          type: string
          format: date-time
          pattern: >-
            ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
          description: When `upload_url` stops working, an hour after it was made.
      required:
        - id
        - object
        - content_type
        - bytes
        - filename
        - upload_url
        - upload_method
        - upload_headers
        - expires_at
      additionalProperties: false
      description: >-
        Where to send a video's or a sound's bytes before you complete the
        upload.
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            type:
              type: string
              enum:
                - invalid_request_error
                - rate_limit_error
                - authentication_error
                - permission_error
                - conflict_error
                - billing_error
                - api_error
              description: >-
                The kind of error. Branch on `type` and `code`, never on
                `message`.
            code:
              type: string
              enum:
                - invalid_parameter
                - invalid_request
                - conflicting_credentials
                - placeholder_in_path
                - method_not_allowed
                - payload_too_large
                - unsupported_media_type
                - ip_rate_limit_exceeded
                - authentication_required
                - missing_api_key
                - invalid_api_key
                - permission_denied
                - not_found
                - resource_not_found
                - gone
                - conflict
                - rate_limit_exceeded
                - insufficient_credit
                - service_unavailable
                - internal_error
              description: >-
                A stable code for this error. Each one is explained at
                https://www.tryleap.ai/docs/errors.
            message:
              type: string
              description: >-
                What went wrong, written for a person. It can change; don't
                parse it.
            param:
              description: >-
                For a `400`, the field at fault, such as `input.prompt`;
                otherwise null.
              type:
                - string
                - 'null'
            doc_url:
              description: A page that explains this error, when there is one.
              type:
                - string
                - 'null'
            request_id:
              type: string
              description: >-
                This request's ID, as in the `X-Request-Id` header. Include it
                when you contact support.
          required:
            - type
            - code
            - message
            - param
            - doc_url
            - request_id
          additionalProperties: false
      required:
        - error
      additionalProperties: false
  headers:
    X-Request-Id:
      required: true
      description: >-
        This request's ID. Include it when you contact support; it's also
        `request_id` in an error.
      schema:
        type: string
        description: >-
          This request's ID. Include it when you contact support; it's also
          `request_id` in an error.
        example: req_01J9Z8Q4N2K7T5V3X6Y8B0C1D2
    RateLimit-Limit:
      required: true
      description: Requests allowed per window from your client.
      schema:
        type: integer
        minimum: 0
        maximum: 9007199254740991
        description: Requests allowed per window from your client.
        example: 300
    RateLimit-Remaining:
      required: true
      description: Requests left in the current window.
      schema:
        type: integer
        minimum: 0
        maximum: 9007199254740991
        description: Requests left in the current window.
        example: 299
    RateLimit-Reset:
      required: true
      description: Seconds until the window resets.
      schema:
        type: integer
        minimum: 0
        maximum: 9007199254740991
        description: Seconds until the window resets.
        example: 42
    Retry-After:
      required: true
      description: Seconds to wait before you retry.
      schema:
        type: integer
        minimum: 0
        maximum: 9007199254740991
        description: Seconds to wait before you retry.
        example: 42
  responses:
    InvalidParameterOrConflictingCredentials:
      description: '`invalid_parameter`, `conflicting_credentials`'
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimit-Limit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimit-Remaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            invalid_parameter:
              value:
                error:
                  type: invalid_request_error
                  code: invalid_parameter
                  message: Invalid request parameters.
                  param: null
                  doc_url: null
                  request_id: req_8kQ2vX9mR4tL6nB1cW3yZ5aD
            conflicting_credentials:
              value:
                error:
                  type: invalid_request_error
                  code: conflicting_credentials
                  message: Send one API key.
                  param: null
                  doc_url: null
                  request_id: req_8kQ2vX9mR4tL6nB1cW3yZ5aD
    AuthenticationRequired:
      description: '`authentication_required`'
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimit-Limit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimit-Remaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            authentication_required:
              value:
                error:
                  type: authentication_error
                  code: authentication_required
                  message: Authentication is required.
                  param: null
                  doc_url: null
                  request_id: req_8kQ2vX9mR4tL6nB1cW3yZ5aD
    InsufficientCredit:
      description: '`insufficient_credit`'
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimit-Limit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimit-Remaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            insufficient_credit:
              value:
                error:
                  type: billing_error
                  code: insufficient_credit
                  message: Not enough credit. Add credits to keep generating.
                  param: null
                  doc_url: null
                  request_id: req_8kQ2vX9mR4tL6nB1cW3yZ5aD
    PermissionDenied:
      description: '`permission_denied`'
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimit-Limit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimit-Remaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            permission_denied:
              value:
                error:
                  type: permission_error
                  code: permission_denied
                  message: Permission denied.
                  param: null
                  doc_url: null
                  request_id: req_8kQ2vX9mR4tL6nB1cW3yZ5aD
    RateLimitExceeded:
      description: '`rate_limit_exceeded`'
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimit-Limit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimit-Remaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimit-Reset'
        Retry-After:
          $ref: '#/components/headers/Retry-After'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            rate_limit_exceeded:
              value:
                error:
                  type: rate_limit_error
                  code: rate_limit_exceeded
                  message: Too Many Requests
                  param: null
                  doc_url: null
                  request_id: req_8kQ2vX9mR4tL6nB1cW3yZ5aD
  securitySchemes:
    ApiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        Your workspace API key, `leap_...`. Create one at
        https://app.tryleap.ai/go/api, and keep it on your server.
    Bearer:
      type: http
      scheme: bearer
      description: >-
        The same API key as `Authorization: Bearer leap_...`, the way most HTTP
        clients and coding agents send one. Send one header or the other; two
        different keys are a `400`.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.