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

# Files API

> Upload files once and reuse them across Orq.ai as knowledge base datasources and batch job sources. Manage the full file lifecycle with the /v2/files API: upload, list, retrieve, update, download, and delete.

**Use Cases**

* Reusing the same document across many API operations (datasource creation, batch jobs, downloads) without uploading it again.
* Grounding agents and deployments with knowledge base datasources.
* Storing JSONL datasets as files for batch jobs.
* Giving code interpreter tools access to project documents.

***

Upload a file once with the **Files API** (`/v2/files`), then reuse it across **Orq.ai**: create a knowledge base datasource from it, feed a batch job, or download its content through a presigned URL.

For sending inline image, PDF, or audio content directly in a request, see [Multimodal inputs and generation](/docs/ai-gateway/features/multimodal).

<CardGroup cols={2}>
  <Card title="Upload" icon="upload" href="#upload-a-file">
    Create a file with a JSON body or multipart form data.
  </Card>

  <Card title="Download" icon="download" href="#download-file-content">
    Get a presigned URL valid for one hour.
  </Card>

  <Card title="Knowledge base" icon="brain" href="#from-file-to-knowledge-base">
    Turn an uploaded file into a datasource for retrieval.
  </Card>

  <Card title="Manage" icon="list" href="#list-update-and-delete-files">
    List, update metadata, and delete files.
  </Card>
</CardGroup>

## Upload a file

[`POST /v2/files`](/reference/files/upload-a-file) accepts a JSON body or `multipart/form-data`.

**JSON body fields:**

| Field          | Type   | Description                                                                                 |
| -------------- | ------ | ------------------------------------------------------------------------------------------- |
| `filename`     | string | Required. Name of the file, including the extension.                                        |
| `content`      | string | Required. Base64-encoded file contents.                                                     |
| `purpose`      | string | Intended usage. Defaults to `retrieval`.                                                    |
| `content_type` | string | MIME type of the content, for example `application/pdf`.                                    |
| `project_id`   | string | Project the file is created in. Project-scoped API keys default to the key's bound project. |

The upload request uses `filename`; the response file object and the `PATCH` update use `file_name`.

For multipart uploads, send the file in the `file` form field and set `purpose` and `project_id` as additional form fields. The MIME type is read from the file part's `Content-Type` header.

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl --request POST \
       --url https://api.orq.ai/v2/files \
       --header 'accept: application/json' \
       --header 'authorization: Bearer $ORQ_API_KEY' \
       --header 'content-type: multipart/form-data' \
       --form file='@contract.pdf' \
       --form purpose='retrieval'
  ```

  ```bash cURL (JSON) theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl --request POST \
       --url https://api.orq.ai/v2/files \
       --header 'accept: application/json' \
       --header 'authorization: Bearer $ORQ_API_KEY' \
       --header 'content-type: application/json' \
       --data '{
         "filename": "contract.pdf",
         "content": "<base64-encoded-content>",
         "content_type": "application/pdf",
         "purpose": "retrieval"
       }'
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import { Orq } from "@orq-ai/node";
  import fs from "node:fs";

  const orq = new Orq({
    apiKey: process.env["ORQ_API_KEY"] ?? "",
  });

  async function run() {
    const result = await orq.files.create({
      filename: "contract.pdf",
      content: fs.readFileSync("contract.pdf").toString("base64"),
      contentType: "application/pdf",
      purpose: "FILE_PURPOSE_RETRIEVAL",
    });

    console.log(result);
  }

  run();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  from orq_ai_sdk import Orq
  import base64
  import os

  with Orq(api_key=os.getenv("ORQ_API_KEY", "")) as orq:
      with open("contract.pdf", "rb") as f:
          content = base64.b64encode(f.read()).decode("utf-8")

      res = orq.files.create(
          filename="contract.pdf",
          content=content,
          content_type="application/pdf",
          purpose="FILE_PURPOSE_RETRIEVAL",
      )

      print(res)
  ```
</CodeGroup>

### Purposes

| Purpose                | Description                                                               |
| ---------------------- | ------------------------------------------------------------------------- |
| `retrieval`            | Default. General-purpose documents; usable as knowledge base datasources. |
| `knowledge_datasource` | Documents chunked and indexed into a knowledge base.                      |
| `batch`                | JSONL datasets for batch inference jobs. Allows larger files.             |
| `code_interpreter`     | Documents available to code interpreter tools.                            |

The REST API accepts lowercase purpose values on input (for example `retrieval`); the response object returns the prefixed form (for example `FILE_PURPOSE_RETRIEVAL`). The SDKs use the prefixed form for both input and output.

### The file object

A successful upload returns the file object under a `file` key:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "file": {
    "file_id": "file_01JA5D27ZVW2N702Z0D3B1G8EK",
    "purpose": "FILE_PURPOSE_RETRIEVAL",
    "file_name": "contract.pdf",
    "bytes": "245760",
    "created_at": "2026-08-10T12:00:00Z",
    "project_id": "project_01JA5D27ZVW2N702Z0D3B1G8EK"
  }
}
```

| Field        | Type   | Description                                                       |
| ------------ | ------ | ----------------------------------------------------------------- |
| `file_id`    | string | Unique identifier, with a `file_` prefix.                         |
| `purpose`    | string | Declared usage category.                                          |
| `file_name`  | string | Display name, including the extension.                            |
| `bytes`      | string | Size of the uploaded file in bytes, returned as a decimal string. |
| `created_at` | string | Time when the file was created.                                   |
| `project_id` | string | Project the file belongs to.                                      |

Keep the `file_id` for later operations: retrieval, metadata updates, downloads, and datasource creation.

## Files and model calls

Model calls receive file content inline. Images and PDFs are passed as public URLs or base64 data URIs in the message content array. See [Multimodal inputs and generation](/docs/ai-gateway/features/multimodal) for the exact content parts.

To use an uploaded file in a model call, index it into a knowledge base and attach the knowledge base to the deployment or agent. See [From file to knowledge base](#from-file-to-knowledge-base) and [Run Agents: Attach Files](/docs/ai-studio/ai-engineering/run-agents#attach-files).

## Download file content

[`GET /v2/files/{file_id_or_path}/content`](/reference/files/download-file-content) returns a presigned URL for downloading the file content.

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl --request GET \
       --url https://api.orq.ai/v2/files/file_01JA5D27ZVW2N702Z0D3B1G8EK/content \
       --header 'accept: application/json' \
       --header 'authorization: Bearer $ORQ_API_KEY'
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import { Orq } from "@orq-ai/node";

  const orq = new Orq({
    apiKey: process.env["ORQ_API_KEY"] ?? "",
  });

  async function run() {
    const result = await orq.files.getContent({
      fileIdOrPath: "file_01JA5D27ZVW2N702Z0D3B1G8EK",
    });

    console.log(result);
  }

  run();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  from orq_ai_sdk import Orq
  import os

  with Orq(api_key=os.getenv("ORQ_API_KEY", "")) as orq:
      res = orq.files.get_content(file_id_or_path="file_01JA5D27ZVW2N702Z0D3B1G8EK")

      print(res)
  ```
</CodeGroup>

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "download_url": "https://storage.orq.ai/..."
}
```

<Note>
  Presigned URLs expire after one hour. Call the endpoint again to get a fresh URL.
</Note>

## List, update, and delete files

**List files:** [`GET /v2/files`](/reference/files/list-all-files). Results are sorted by `file_id` in ascending order, so the most recently created files appear last. Page through with `limit` (default 10, maximum 200). Set `starting_after` to the `file_id` of the last item of the previous page, or `ending_before` to the first item. Filter by `purpose` or `project_id`.

**Retrieve a file:** [`GET /v2/files/{file_id}`](/reference/files/retrieve-a-file) returns the file object.

**Update metadata:** [`PATCH /v2/files/{file_id}`](/reference/files/update-a-file) updates the file name. The body accepts `file_name`; content cannot be changed after upload.

**Delete a file:** [`DELETE /v2/files/{file_id}`](/reference/files/delete-a-file) permanently deletes the file record and its stored content. Deletion cannot be undone.

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl --request DELETE \
       --url https://api.orq.ai/v2/files/file_01JA5D27ZVW2N702Z0D3B1G8EK \
       --header 'accept: application/json' \
       --header 'authorization: Bearer $ORQ_API_KEY'
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import { Orq } from "@orq-ai/node";

  const orq = new Orq({
    apiKey: process.env["ORQ_API_KEY"] ?? "",
  });

  async function run() {
    const fileId = "file_01JA5D27ZVW2N702Z0D3B1G8EK";

    const list = await orq.files.list({ limit: 10 });
    const file = await orq.files.get({ fileId });
    const updated = await orq.files.update({
      fileId,
      updateFileRequest: { fileName: "renamed.txt" },
    });
    await orq.files.delete({ fileId });

    console.log({ list, file, updated });
  }

  run();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  from orq_ai_sdk import Orq
  import os

  with Orq(api_key=os.getenv("ORQ_API_KEY", "")) as orq:
      file_id = "file_01JA5D27ZVW2N702Z0D3B1G8EK"

      listing = orq.files.list(limit=10)
      file = orq.files.get(file_id=file_id)
      updated = orq.files.update(file_id=file_id, file_name="renamed.txt")
      orq.files.delete(file_id=file_id)

      print(listing, file, updated)
  ```
</CodeGroup>

## Supported types and limits

| Purpose                                                 | Maximum size | Supported types                     |
| ------------------------------------------------------- | ------------ | ----------------------------------- |
| `retrieval`, `knowledge_datasource`, `code_interpreter` | 10 MB        | TXT, PDF, DOC, DOCX, CSV, XLS, XLSX |
| `batch`                                                 | 100 MB       | JSONL (JSONL or NDJSON content)     |

Files with multiple filename extensions are rejected. The stored MIME type comes from the declared `content_type` or the filename extension.

## Data handling and lifecycle

* **Project scope**: files belong to the project they were created in. An API key can only access files in the projects it is authorized for.
* **Persistence**: file content persists until explicitly deleted with `DELETE /v2/files/{file_id}`. There is no automatic expiry.
* **Presigned URLs**: download links expire after one hour and can be regenerated at any time.
* **Cleanup**: delete files that are no longer referenced. For long-running agents and deployments, delete superseded documents after the consuming run finishes to avoid unbounded storage.

For data handling, retention, and privacy practices, see [Data compliance and privacy](/docs/ai-studio/organization/data-compliance). For zero-data-retention deployments, see [Sovereign AI & ZDR](/docs/enterprise/sovereign-ai).

## From file to knowledge base

The file-based knowledge base flow uploads a document, then points a datasource at the resulting `file_id`. **Orq.ai** chunks and indexes the file automatically.

1. Upload the document with `POST /v2/files` and save the `file_id`.
2. Create a datasource with `POST /v2/knowledge/{knowledge_id}/datasources`, passing `file_id` and `display_name`.
3. Attach the knowledge base to a deployment or agent to ground responses in the indexed content.

For the upload and datasource code samples, chunking options, and memory stores, see [Knowledge Bases & Memory Stores](/docs/ai-studio/ai-engineering/knowledge-bases-memory-stores).

## Related reference

* [Upload a file](/reference/files/upload-a-file) · [List all files](/reference/files/list-all-files) · [Retrieve a file](/reference/files/retrieve-a-file) · [Update a file](/reference/files/update-a-file) · [Delete a file](/reference/files/delete-a-file) · [Download file content](/reference/files/download-file-content)
* [Files SDK Reference](/reference/sdk/files)
