# Files

> Upload material for the agent and download what it produced.


RavChat agents work in a real project workspace and produce files — study sheets, source compilations, generated media. The Files API is how you upload material for the agent and download what it made.

## Endpoints

| Endpoint | Behavior |
|---|---|
| `POST /v1/files` | multipart `file` + `purpose`; optional `project_id`, `workspace_id`, `path` |
| `GET /v1/files?project_id=` | `{object:"list", data, first_id, last_id, has_more}` |
| `GET /v1/files/{id}` | file object |
| `GET /v1/files/{id}/content` | raw bytes |
| `DELETE /v1/files/{id}` | `{id, object:"file", deleted:true}` |

The file object is the OpenAI shape plus RavChat vendor fields (`project_id`, `path`, `source`, `session_id`). `source` is `user`, `assistant`, or `media`.

## Mutability — read this

<Warning>
Two kinds of file objects, honestly distinguished — this is a deliberate deviation from OpenAI's immutable file store, because the workspace is the product.
</Warning>

<AccordionGroup>
  <Accordion title="Managed uploads — immutable" icon="lock">
    `POST /v1/files` **without** an explicit `path`: stored in a managed location, immutable. OpenAI-exact semantics — each upload is a new object; overwrites are rejected.
  </Accordion>
  <Accordion title="Live project files — mutable" icon="pen">
    Agent-produced files, or uploads **with** an explicit `path`: real files in a living workspace. The agent may modify them after you list them. `/content` always serves current disk truth; `bytes` refreshes on retrieve/list; if the underlying file is deleted, the object 404s.
  </Accordion>
</AccordionGroup>

## Uploading for the agent

A file uploaded with `project_id` (or your key's default project) lands in the workspace the agent reads. Reference it in a completion with a standard file content part:

```json
{"role": "user", "content": [
  {"type": "text", "text": "Summarize this source sheet."},
  {"type": "file", "file": {"file_id": "file-rav-…"}}
]}
```

`file_data` (base64 data-URL) + `filename` is also accepted and stored through the same upload path. The `file_id` must be within your key's project scope.

## Agent-produced files

Files the agent produces during a turn are indexed and returned in the response's `x_ravchat.files`. **The promise is "observed files":** the index captures files the agent explicitly surfaced (shown files, generated media, resolved session outputs) — not every byte the agent may have touched. All indexed files also appear in the project file listing and persist after the session ends.

## Limits

- 50 MB per file (v1).
- Per-project storage quota applies (plan-dependent).
- File endpoints have their own rate limits, separate from completions.
- Files are never auto-deleted by TTL — delete explicitly. (`expires_after` is not supported in v1.)
