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

# Create Presigned Upload URL

> Create a short-lived presigned URL for uploading media files. Upload the raw file bytes
to `presigned_url` using every header returned in `required_headers`, then pass
`public_url` as a model input.




## OpenAPI

````yaml /openapi_specs/models.json post /v1/upload/presign
openapi: 3.0.3
info:
  title: each::labs Official API v1
  description: >
    Official each::labs API V1.

    This API provides access to our comprehensive AI model catalog and other
    resources.


    ## Public contract notes


    - Public API routes handled by request logging include `X-Request-Id` for
      support and log correlation. Clients may send `X-Request-Id`; otherwise
      api-service generates one. Root, health, and metrics endpoints are excluded.
    - REST error bodies keep the backward-compatible JSON shape used by existing
      clients. Most errors include at least `error`; some shared error paths also
      include `status` and `details`. Use the HTTP status code as the primary
      programmatic signal unless an endpoint documents a richer envelope.
    - Rate-limit and retry headers are endpoint-dependent. If a response
    includes
      `Retry-After`, honor it before retrying; otherwise use bounded exponential
      backoff for retryable 429/5xx responses.
    - api-service exposes single workflow trigger through
      `/v1/workflows/trigger/{workflowID}/{versionID}`. Bulk workflow trigger is
      not routed through api-service; use the workflows-engine public API directly
      where bulk trigger is required.
  version: 1.0.0
  contact:
    name: API Support
    email: support@eachlabs.ai
  x-logo:
    url: ./logo-white.svg
    altText: each::labs
servers:
  - url: https://api.eachlabs.ai
    description: Production server
security: []
tags:
  - name: AI Models
    description: Endpoints for listing and retrieving AI models and other resources.
  - name: AI Models Prediction
    description: Endpoints for managing model predictions
  - name: Uploads
    description: Endpoints for uploading files that can be used as model inputs.
  - name: Executions
    description: Endpoints for listing execution history.
  - name: Workflows
    description: Endpoints for triggering workflow executions through api-service.
  - name: OpenAI Compatibility
    description: OpenAI-compatible endpoints for LLM Router requests.
  - name: Webhooks
    description: >
      Endpoints for retrieving webhook information and delivery history.


      **Note:** Currently, webhooks are only supported for Workflows V2. We are
      actively expanding webhook support to other services and will update this
      documentation as new integrations become available.
paths:
  /v1/upload/presign:
    post:
      tags:
        - Uploads
      summary: Create Presigned Upload URL
      description: >
        Create a short-lived presigned URL for uploading media files. Upload the
        raw file bytes

        to `presigned_url` using every header returned in `required_headers`,
        then pass

        `public_url` as a model input.
      operationId: presignUpload
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PresignUploadRequest'
            example:
              content_type: image/png
              file_type: image
      responses:
        '200':
          description: Presigned upload URL created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PresignUploadResponse'
              example:
                id: 0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0
                presigned_url: >-
                  https://eachlabs-storage.s3.amazonaws.com/uploads/...?X-Amz-Signature=...
                public_url: >-
                  https://cdn-us.eachlabs.ai/uploads/0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0.png
                expires_at: '2026-12-08T18:15:00Z'
                required_headers:
                  x-amz-meta-file-id: 0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - ApiKeyAuth: []
components:
  schemas:
    PresignUploadRequest:
      type: object
      required:
        - content_type
      properties:
        content_type:
          type: string
          description: MIME type of the file to upload
          example: image/png
        file_type:
          type: string
          description: High-level file category
          enum:
            - image
            - video
            - audio
            - other
          example: image
        expires_in_seconds:
          type: integer
          description: >-
            How long the stored file is retained before automatic deletion, in
            seconds. Sets `expires_at` in the response. Defaults to 180 days
            when omitted; clamped to a minimum of 60 seconds and a maximum of
            365 days (31536000). Does not affect the 15-minute upload-URL
            lifetime.
          minimum: 60
          maximum: 31536000
          example: 604800
    PresignUploadResponse:
      type: object
      properties:
        id:
          type: string
          description: Upload identifier
          example: 0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0
        presigned_url:
          type: string
          format: uri
          description: Short-lived URL for uploading raw file bytes
          example: >-
            https://eachlabs-storage.s3.amazonaws.com/uploads/...?X-Amz-Signature=...
        public_url:
          type: string
          format: uri
          description: Public URL to pass as a model input after upload succeeds
          example: >-
            https://cdn-us.eachlabs.ai/uploads/0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0.png
        expires_at:
          type: string
          format: date-time
          description: >-
            When the stored file is automatically deleted (its retention
            deadline). Defaults to 180 days out; controlled by
            `expires_in_seconds`. Not the upload-URL deadline — the presigned
            URL only accepts uploads for 15 minutes after issuance.
          example: '2026-12-08T18:15:00Z'
        required_headers:
          type: object
          description: Headers that must be sent verbatim with the upload PUT request
          additionalProperties:
            type: string
          example:
            x-amz-meta-file-id: 0dce0f44-b8a5-4f30-91d4-5f6b0c221bf0
    Error:
      type: object
      description: >
        Backward-compatible REST error body. Endpoint-specific handlers may
        return only

        `error`; shared error paths may also include `status` and `details`.
      properties:
        status:
          type: integer
          description: HTTP status code, when returned by the shared error handler.
          example: 400
        error:
          type: string
          description: Safe user-facing error message.
          example: error message
        details:
          nullable: true
          description: Optional validation or request details for client errors.
      required:
        - error
  responses:
    BadRequest:
      description: Bad request
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: slug parameter is required
    Unauthorized:
      description: Authentication required or invalid credentials
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Invalid or missing API key
    InternalServerError:
      description: Internal server error
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: 'Failed to fetch models: internal error'
  headers:
    RequestId:
      description: >-
        Request correlation ID. Echoes the incoming `X-Request-Id` header or a
        generated ID.
      schema:
        type: string
      example: 123e4567-e89b-12d3-a456-426614174000
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: API key for authentication

````