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

# Upload a file

> POST /v1/files — upload a file and get back a reusable file_id.

Infery's Files API mirrors OpenAI's Files API exactly. Upload a file, get back a `file_id`, reference it in chat completions.

## Upload

<CodeGroup>
  ```bash curl theme={null}
  curl https://api.infery.ai/v1/files \
    -H "Authorization: Bearer $INFERY_API_KEY" \
    -F purpose=assistants \
    -F file=@./report.pdf
  ```

  ```python python theme={null}
  from openai import OpenAI
  client = OpenAI(api_key=API_KEY, base_url="https://api.infery.ai/v1")
  f = client.files.create(file=open("report.pdf", "rb"), purpose="assistants")
  print(f.id)  # file_abc123...
  ```

  ```typescript node theme={null}
  const f = await client.files.create({
    file: fs.createReadStream('./report.pdf'),
    purpose: 'assistants',
  });
  console.log(f.id);
  ```
</CodeGroup>

Response:

```json theme={null}
{
  "id": "file_1hR9xTPZqK4mVLc2nJ7fY5wB",
  "object": "file",
  "bytes": 245192,
  "created_at": 1713204900,
  "filename": "report.pdf",
  "purpose": "assistants",
  "status": "processed"
}
```

## Purposes

| purpose      | Used for                                 |
| ------------ | ---------------------------------------- |
| `assistants` | General-purpose attachment (most common) |
| `vision`     | Image inputs                             |
| `user_data`  | Per-user documents (RAG, analysis)       |
| `batch`      | Batch inference inputs (coming soon)     |

## Reference in chat

```json theme={null}
{
  "messages": [{
    "role": "user",
    "content": [
      {"type": "text", "text": "Summarise this"},
      {"type": "file", "file_id": "file_abc123..."}
    ]
  }]
}
```

The gateway resolves the id, fetches bytes from our storage, and injects them into the provider call as inline content. **Workspace-scoped**: you only see files uploaded to your own workspace.

## Idempotency

```
Idempotency-Key: my-unique-request-2026-04-15
```

Same key within 24 h returns the original `file_id` instead of uploading twice. Key format: `[A-Za-z0-9_.-:]{1,255}`.

## Security

* **MIME sniffing** via magic bytes — we don't trust `Content-Type`. Mismatch → 400.
* **Workspace isolation** — cross-workspace lookup returns 404 (we don't leak existence).
* **Private storage** — GCS objects have `Cache-Control: private, max-age=0`. Download only via our signed proxy.
* **Size and count caps** — plan-based, see [Plans](/billing/subscription-plans).
* **Filename sanitisation** — basename stripped, control chars removed, max 255 chars.

## Quotas

Your plan caps:

* `max_file_size_bytes` — single upload
* `max_files_per_workspace` — total count
* `max_storage_bytes_per_workspace` — total size

Response headers show your current usage: `X-Storage-Used-Bytes`, `X-Storage-Limit-Bytes`, `X-Files-Used`, `X-Files-Limit`.


## OpenAPI

````yaml openapi.json POST /v1/files
openapi: 3.0.0
info:
  title: Infery Gateway
  description: >-
    Infery Inference Gateway — OpenAI-compatible API for LLMs, embeddings,
    images, audio, and video
  version: '1.0'
  contact: {}
servers:
  - url: https://api.infery.ai
    description: Production
  - url: http://localhost:3001
    description: Local
security: []
tags: []
paths:
  /v1/files:
    post:
      tags:
        - Files
      summary: Upload a file
      operationId: uploadFile
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Same key within 24h returns the originally created file instead of
            uploading twice. Format: [A-Za-z0-9_.-:]{1,255}
          required: false
          schema:
            type: string
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - file
                - purpose
              properties:
                file:
                  type: string
                  format: binary
                  description: Binary file contents.
                purpose:
                  type: string
                  enum:
                    - assistants
                    - vision
                    - user_data
                    - batch
                  description: Intended use of the file.
      responses:
        '201':
          description: File uploaded successfully.
          headers:
            X-Storage-Used-Bytes:
              schema:
                type: integer
              description: Current workspace storage usage
            X-Storage-Limit-Bytes:
              schema:
                type: integer
              description: Plan storage cap
            X-Files-Used:
              schema:
                type: integer
              description: Current file count
            X-Files-Limit:
              schema:
                type: integer
              description: Plan file-count cap
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    example: file_1hR9xTPZqK4mVLc2nJ7fY5wB
                  object:
                    type: string
                    example: file
                  bytes:
                    type: integer
                    example: 245192
                  created_at:
                    type: integer
                    example: 1713204900
                  filename:
                    type: string
                    example: report.pdf
                  purpose:
                    type: string
                    enum:
                      - assistants
                      - vision
                      - user_data
                      - batch
                    example: assistants
                  status:
                    type: string
                    example: processed
        '400':
          description: >-
            Invalid request (missing file/purpose, invalid idempotency key, MIME
            mismatch, etc.)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '401':
          description: Unauthorized — invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '413':
          description: >-
            File exceeds the upload limit (256MB hard cap; plan limits apply
            earlier)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
      security:
        - ApiKey: []
components:
  schemas:
    ErrorResponseDto:
      type: object
      properties:
        error:
          $ref: '#/components/schemas/ErrorDetailDto'
      required:
        - error
    ErrorDetailDto:
      type: object
      properties:
        message:
          type: string
          example: Model not found
          description: Human-readable error message
        type:
          type: string
          example: invalid_request_error
          description: Error category
          enum:
            - invalid_request_error
            - authentication_error
            - permission_error
            - quota_exceeded
            - rate_limit_error
            - server_error
        code:
          type: object
          example: model_not_found
          nullable: true
          description: Stable machine-readable error code
        param:
          type: object
          example: model
          nullable: true
          description: >-
            Name of the request parameter that triggered the error, if
            applicable
      required:
        - message
        - type
        - code
        - param
  securitySchemes:
    ApiKey:
      type: apiKey
      in: header
      name: Authorization
      description: 'API key in format: Bearer inf_***'

````