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

# Initiate upload

> Creates a GCS resumable upload session behind our domain. The caller PUTs file chunks to the returned uploadUrl with Content-Range headers.



## OpenAPI

````yaml /openapi/file-api.json post /v1/uploads
openapi: 3.1.0
info:
  title: Adclear File Proxy API
  version: 1.0.0
  description: >
    File upload service for Adclear. Upload files here before creating
    promotions via the

    [Integration API](https://public-api.adclear.ai/v1/docs).


    ## Authentication


    All endpoints require a Bearer token (`Authorization: Bearer <token>`).

    Two authentication methods are supported:


    - **Clerk JWT** — User identity is extracted from the token.

    - **API Key** — Optionally pass `X-External-User-ID` to identify the
    end-user.
      `X-External-User-Email` is also optional but recommended for audit logging.

    ## Usage


    ### 1. Initiate an upload

    ```

    POST /v1/uploads  { fileName, fileSize, contentType }

    →  201 { uploadId, uploadUrl, maxChunkSize }

    ```


    ### 2. Upload the file in chunks

    PUT file chunks to the returned `uploadUrl` with a `Content-Range` header.

    Each chunk must be at most `maxChunkSize` bytes (default 50 MB).


    ```

    PUT /v1/uploads/{uploadId}

    Content-Range: bytes 0-52428799/123456789

    →  308  (more chunks needed)


    PUT /v1/uploads/{uploadId}

    Content-Range: bytes 52428800-123456788/123456789

    →  200  { status: "completed", uploadId }

    ```


    ### 3. Use the uploadId

    Pass the `uploadId` when creating a promotion or version via the Integration
    API.

    The file is verified automatically at that point.


    ## File size limits


    | Format | Max size |

    |--------|----------|

    | PDF | 30 MB |

    | Image (jpg, png, webp, etc.) | 30 MB |

    | Video (mp4, mov, etc.) | 2 GB |

    | Audio (mp3, wav, etc.) | 2 GB |

    | Document (docx, xlsx, etc.) | 10 MB |


    Files exceeding these limits are rejected at initiation (413 Payload Too
    Large).


    ## Chunk size


    The `maxChunkSize` returned by the initiate endpoint defines the maximum
    bytes per PUT request.

    The default is 50 MB. The final chunk may be smaller.


    ---
servers:
  - url: https://files.adclear.ai
    description: Production
  - url: https://files-staging.adclear.ai
    description: Staging
security:
  - BearerAuth: []
tags:
  - name: Upload
    description: File upload operations (initiate, status, delete)
  - name: Download
    description: File download and streaming (Bearer or signed URL token auth)
externalDocs:
  description: Integration API — create promotions, trigger evaluations
  url: https://public-api.adclear.ai/v1/docs
paths:
  /v1/uploads:
    post:
      tags:
        - Upload
      summary: Initiate upload
      description: >-
        Creates a GCS resumable upload session behind our domain. The caller
        PUTs file chunks to the returned uploadUrl with Content-Range headers.
      operationId: initiateUpload
      parameters:
        - schema:
            type: string
            format: uuid
            description: >-
              Workspace ID fallback. Required when authenticating with a Bearer
              token in environments where cookies cannot be shared (e.g.
              preview). Not needed for API key auth (workspace is embedded in
              the key metadata) or when the workspace cookie is present.
            example: 43dc2a1c-3384-41b5-a6e9-3b2d607d0fae
          required: false
          name: x-adclear-workspace-id
          in: header
        - schema:
            type: string
            description: >-
              Required when authenticating with an API key. Identifies the
              end-user making the request. Ignored when authenticating with a
              Bearer token (the user ID is extracted from the token).
            example: user_abc123
          required: false
          name: x-external-user-id
          in: header
        - schema:
            type: string
            format: email
            description: >-
              Optional. Email of the external user, used for audit logging. Only
              applicable when authenticating with an API key.
            example: user@example.com
          required: false
          name: x-external-user-email
          in: header
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InitiateUploadRequest'
      responses:
        '201':
          description: Upload initiated — use uploadUrl to PUT file chunks
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InitiateUploadResponse'
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: VALIDATION_ERROR
                  message: >-
                    Missing or malformed Content-Range header. Expected: bytes
                    <start>-<end>/<total|*>
                  details:
                    - type: field_error
                      field: fileName
                      message: Required
                correlationId: f47ac10b-58cc-4372-a567-0e02b2c3d479
        '401':
          description: Unauthorized — missing or invalid token/API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: UNAUTHORIZED
                  message: Missing or invalid Bearer token
                correlationId: f47ac10b-58cc-4372-a567-0e02b2c3d479
        '413':
          description: File too large
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: PAYLOAD_TOO_LARGE
                  message: >-
                    File size 104857600 exceeds limit of 31457280 bytes for pdf
                    files
                  details:
                    - type: constraint_violation
                      constraint: max_file_size
                      limit: 31457280
                      actual: 104857600
                correlationId: f47ac10b-58cc-4372-a567-0e02b2c3d479
        '429':
          description: Rate limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests
                  details:
                    - type: retry_info
                      retryAfterSeconds: 30
                correlationId: f47ac10b-58cc-4372-a567-0e02b2c3d479
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: INTERNAL_ERROR
                  message: Internal server error
                correlationId: f47ac10b-58cc-4372-a567-0e02b2c3d479
        '502':
          description: Storage service error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: SERVICE_ERROR
                  message: Storage returned unexpected status 503
                correlationId: f47ac10b-58cc-4372-a567-0e02b2c3d479
      security:
        - BearerAuth: []
components:
  schemas:
    InitiateUploadRequest:
      type: object
      properties:
        fileName:
          type: string
          minLength: 1
          description: Original file name including extension
        fileSize:
          type: integer
          exclusiveMinimum: 0
          description: >-
            Total file size in bytes. Must not exceed the format-specific limit
            (e.g. 30 MB for PDF/images, 2 GB for video/audio, 10 MB for
            documents)
        contentType:
          type: string
          minLength: 1
          description: MIME type (e.g. application/pdf, image/png)
      required:
        - fileName
        - fileSize
        - contentType
    InitiateUploadResponse:
      type: object
      properties:
        uploadId:
          type: string
          format: uuid
          description: Server-generated upload identifier
        uploadUrl:
          type: string
          description: 'Relative URL for chunk uploads: PUT /v1/uploads/{uploadId}'
        maxChunkSize:
          type: integer
          description: >-
            Maximum bytes per PUT chunk request (default 50 MB). Final chunk may
            be smaller.
        correlationId:
          type: string
          format: uuid
          description: Correlation ID for request tracing. Include in support requests.
      required:
        - uploadId
        - uploadUrl
        - maxChunkSize
        - correlationId
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - VALIDATION_ERROR
                - INVALID_REQUEST
                - UNAUTHORIZED
                - FORBIDDEN
                - NOT_FOUND
                - PAYLOAD_TOO_LARGE
                - RATE_LIMITED
                - INTERNAL_ERROR
                - SERVICE_ERROR
            message:
              type: string
            details:
              type: array
              items:
                type: object
                properties:
                  type:
                    type: string
                  field:
                    type: string
                  message:
                    type: string
                  constraint:
                    type: string
                  limit:
                    type: number
                  actual:
                    type: number
                  retryAfterSeconds:
                    type: number
                required:
                  - type
          required:
            - code
            - message
        correlationId:
          type: string
          format: uuid
      required:
        - error
        - correlationId
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: Clerk session JWT or Unkey API key passed as Bearer token

````