Files
Persist a document once, then reference it across chat completions by id - no need to re-upload bytes on every request.
The Files API lets you upload documents once and reference them by id in
chat completions. It is the persistent counterpart to inline
file_data / file_url parts.
POST /v1/files
GET /v1/files
GET /v1/files/:file_id
GET /v1/files/:file_id/content
DELETE /v1/files/:file_idFiles are scoped to the API key's project. Two requests cannot see each other's files, even when they hit the same gateway.
Why use it
Inline file parts (file_data, file_url) are great for one-off
requests. The Files API wins whenever a document is:
- Reused across turns - a 10 MB PDF in a 20-turn conversation costs ~200 MB of upload traffic if you inline it every time. Uploaded once, it costs ~30 bytes per reference.
- Large - inline base64 inflates payload by ~33%. The Files API ingests raw bytes once.
- Reused across sessions - your front-end can drop the bytes after
upload and persist just the
file_id. - Subject to retention rules - explicit
DELETEgives you a clean audit boundary;expires_afterautomates cleanup for batch jobs.
Two ways to attach a file
Both modes use the same {type: 'file'} content part inside chat
completions - they only differ in where the bytes live.
| Mode | Where bytes live | Send each request | Best for |
|---|---|---|---|
| Inline | Nowhere - bytes flow through the gateway only | file_data (base64) or file_url | One-off requests, public URLs |
| Managed (Files API) | Project file storage, scoped per user | file_id (~30 bytes) | Multi-turn, reuse, large files |
Managed files are cached to reduce latency on repeated access, and save on upload bandwidth for repeat requests.
Lifecycle
-
Upload with
POST /v1/files. You get back aFileObjectwithid(file-...),bytes,created_at,purpose, and optionalexpires_at. -
Reference the
idfrom chat completions:{ "type": "file", "file": { "file_id": "file-abc123..." } } -
Inspect at any time with
GET /v1/filesorGET /v1/files/:id. -
Delete with
DELETE /v1/files/:idwhen done.
Storage limits
| Constraint | Value |
|---|---|
| Max single upload | 100 MB |
| Per-request inline file budget | 50 MB across all parts |
expires_after[seconds] range | 3600 (1 hour) - 2592000 (30 days) |
Default retention without expires_after | indefinite, until deleted |
File object
The shape returned by upload / retrieve / list endpoints, and accepted by
the OpenAI SDK as FileObject.
| Field | Type | Description |
|---|---|---|
id | string | Unique file identifier, prefixed with file-. Use this anywhere a file_id is accepted. |
object | 'file' | Always file. |
bytes | integer | Size of the uploaded file in bytes. |
created_at | integer | Unix timestamp (seconds) when the file was uploaded. |
filename | string | Original filename as sent in the upload form. |
purpose | string | One of assistants, batch, fine-tune, vision, user_data, evals. Set at upload time. |
status | string | Processing state: uploaded, processed, or error. |
expires_at | integer | Optional Unix timestamp when the file will be auto-deleted. Only present when expires_after was set at upload. |
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| POST | /v1/files | Upload file |
| GET | /v1/files | List files |
| GET | /v1/files/:id | Retrieve file |
| GET | /v1/files/:id/content | Retrieve content |
| DELETE | /v1/files/:id | Delete file |
Every endpoint expects a bearer token in the Authorization header.
Create keys at Manage API Keys.
Supported file formats
When a file is referenced in chat completions, the gateway extracts its text content automatically. The following formats are supported:
| Category | Formats |
|---|---|
| Documents | PDF, DOCX, DOC, ODT, Pages, RTF |
| Presentations | PPTX, PPT, Keynote |
| Spreadsheets | XLSX, XLS |
| Text-based | Any plain text, source code, config, markup, or data file (e.g. .txt, .md, .json, .csv, .html, .py, .ts, .yaml, .sql, .sh, and hundreds more) |
Text-based files are detected by MIME type or extension. If it starts
with text/ or is a known structured format (JSON, XML, YAML, TOML,
GraphQL, Protobuf, etc.), it will be read as-is without conversion.
Extraction results are cached per unique file content, so repeated references to the same file have significantly lower latency.
Errors
All errors follow the standard error shape:
{ "error": { "type": "invalid_request_error", "message": "..." } }| Status | error.type | Meaning |
|---|---|---|
400 | invalid_request_error | Missing or invalid form fields. |
401 | invalid_request_error | Missing or invalid API key. |
403 | invalid_request_error | API key has no associated user. |
404 | invalid_request_error | No such File object: file-... |
413 | invalid_request_error | Upload exceeds the 100 MB max. |
500 | internal_server_error | Unexpected failure. |
For full compatibility with the official OpenAI client, the gateway tags
every Files-domain error as invalid_request_error regardless of HTTP
status. SDKs branch on the status code (NotFoundError for 404, etc.).