Upload a file once and reference it by id in chat completions and other requests.
The Files API lets you upload a file once and reference it by id in any number of requests, instead of re-encoding the same bytes into every message. Upload images, audio, PDFs, or plain text, then pass the returned id as a file content part in chat completions. Uploads and storage are free — you are only billed for the model requests that use the files.
| Method | Path | Description |
|---|---|---|
| POST | /v1/files | Upload a file |
| GET | /v1/files | List your files |
| GET | /v1/files/{id} | Retrieve a file's metadata |
| DELETE | /v1/files/{id} | Delete a file |
| GET | /v1/files/{id}/content | Download the raw bytes |
Authenticate every request with your key: Authorization: Bearer $OPENDUNES_API_KEY.
Send a multipart form with the bytes in a field named file. An optional purpose string (max 64 characters) is stored with the file; it defaults to user_data.
A successful upload returns 201 with the file object. The id is what you reference in later requests; timestamps are unix seconds.
The file's type is decided from its actual bytes, never from the filename or the claimed content type — a .png that is really an archive is rejected as unsupported_file_type.
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | integer | No | Page size, 1–100 (default: 20) |
after | string | No | A file id (UUID) — returns files older than it (cursor pagination); non-UUID values are rejected with a validation error |
Files come back newest-first:
When has_more is true, pass the last file's id as after to fetch the next page.
GET /v1/files/{id} returns the same file object as the upload response. An unknown, expired, or someone else's id returns 404 with {"error":"not_found","message":"File not found."}.
Deleting a file does not rewrite replies you already received — but any future request that references the id fails, and if the file was attached in a stored chat conversation, that attachment silently disappears from the conversation the next time it is read.
GET /v1/files/{id}/content streams the raw bytes back as an attachment with the file's stored content type.
Reference an uploaded file anywhere a message accepts content parts by sending a file part with the file_id:
The reference is expanded server-side into the right inline shape for the file's type before the request is forwarded, so the model you pick still needs the matching capability — vision for images, audio input for audio, file/PDF input for PDFs and text. A mismatch is not caught before forwarding: the provider rejects the request, and the rejection surfaces through the standard error envelope with the provider's message (see Errors and Debugging).
Image generation input_references and video generation frame_images accept the same part — for those, the referenced file must be an image.
Do not combine file_id with file_data in one part: a part that carries file_data is treated as classic inline content and the id is ignored.
Supported types (detected from the bytes): images (png, jpeg, webp, gif), audio (mp3, wav, flac, m4a, ogg, aac), PDF, and plain text — any file whose bytes read as text is accepted and stored as text/plain (txt, md, csv, and json uploads keep their extensions; other text files are stored as .txt).
File endpoints use the standard error envelope — unsupported_file_type, quota_exceeded, and invalid_file_reference are listed with the rest of the codes in Errors and Debugging. One exception: an upload over the 32 MB per-file cap is rejected by request validation and returns the standard 422 validation body ({"message": …, "errors": {"file": […]}}), not the flat error envelope.