Skip to main content

REST API: Files

File endpoints allow you to upload images, audio, and documents, then reference them in graph messages by file_id.

Base path: /v1/files


POST /v1/files/upload

Upload a file and receive a file_id to use in future messages.

Request: Content-Type: multipart/form-data

FieldTypeDescription
filebinaryThe file to upload (required, must have a filename)

Accepted types:

The server accepts any content type by default. MEDIA_ALLOWED_CONTENT_TYPES is empty out of the box, and an empty allowlist means allow everything. Set it to restrict uploads:

MEDIA_ALLOWED_CONTENT_TYPES=image/*,application/pdf

Entries may be exact (image/png) or wildcard subtype (image/*). A rejected type returns 415.

Types commonly sent to an agent: image/jpeg, image/png, image/webp, image/gif, audio/mpeg, audio/wav, audio/ogg, application/pdf, text/plain.

Size limit: MEDIA_MAX_SIZE_MB, default 25.0. Exceeding it returns 413. The body is read in 1 MiB chunks with a running size cap, so an oversized or chunked upload is rejected before it is buffered whole.

Example:

curl -X POST http://127.0.0.1:8000/v1/files/upload \
-H "Authorization: Bearer $TOKEN" \
-F "file=@photo.jpg"

Response:

{
"success": true,
"data": {
"file_id": "f_abc123",
"mime_type": "image/jpeg",
"size_bytes": 24576,
"filename": "photo.jpg",
"extracted_text": null,
"url": "/v1/files/f_abc123",
"direct_url": null,
"direct_url_expires_at": null
}
}
FieldDescription
file_idOpaque storage key. Reference this from message content blocks.
mime_typeThe content type the server recorded
size_bytesStored size
filenameOriginal filename
extracted_textExtracted document text, when DOCUMENT_HANDLING=extract_text and the type is extractable. null otherwise.
urlAPI-relative retrieval path
direct_urlSigned direct URL, when the storage backend can produce one
direct_url_expires_atExpiry of the signed URL, as a Unix timestamp

The uploader is recorded as the file's owner. Every read path checks it, and a file owned by another user returns 404, not 403, so the API never confirms that a foreign file_id exists.

For how to reference an uploaded file from a message, see Multimodal and vision.


GET /v1/files/{file_id}

Retrieve a file by its ID.

Response: Raw file bytes with the correct Content-Type header.

curl http://127.0.0.1:8000/v1/files/f_abc123 --output photo.jpg

GET /v1/files/{file_id}/info

Get metadata for a file without downloading it.

Response:

{
"file_id": "f_abc123",
"filename": "photo.jpg",
"content_type": "image/jpeg",
"size_bytes": 24576,
"created_at": "2026-04-08T10:00:00Z"
}

Using a file_id in a message

Include the file_id in a message content array when invoking the graph:

{
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "What is in this image?"},
{"type": "image", "file_id": "f_abc123"}
]
}
],
"config": {"thread_id": "media-thread"}
}

The graph receives an ImageBlock (or AudioBlock for audio files) containing the file reference.


Error responses

StatusDescription
400Missing filename or empty file
413File exceeds MAX_REQUEST_SIZE
404file_id not found

Authentication

File uploads require files:upload permission. File reads require files:read.