Skip to content

Files

For developers who connect a client to OpenBot or extend its server. The examples need the access stated on this page. Start with the developer manual.

A file is a picture, a PDF, or another document that you give to OpenBot. You upload it once, and then you name it in a message to a Bot. The model of the Bot sees the file.

OpenBot keeps the bytes of each file in object storage: a service that stores files and speaks the S3 API, such as AWS S3, Cloudflare R2, MinIO or RustFS. A platform admin sets up the storage. See Set up storage.

Every file belongs to one member of one organization. Other people cannot read it.


There are two ways to upload. A platform admin can turn each of them on or off.

Send the file as multipart/form-data to POST /v1/files. The field file has the file. OpenBot takes other fields, such as purpose, but it does not use them.

Terminal window
curl -H "Authorization: Bearer $OPENBOT_TOKEN" \
-F file=@photo.png \
https://api.example.com/v1/files
{
"id": "file_6f1c…",
"object": "file",
"filename": "photo.png",
"mediaType": "image/png",
"bytes": 52731,
"status": "ready",
"createdAt": 1793000000000
}

The file is ready at once. OpenBot reads the media type from the form. When the form says application/octet-stream, OpenBot guesses the type from the end of the file name, such as .png or .pdf.

For large files, the client can put the bytes in storage itself. Then the bytes do not go through OpenBot.

  1. Ask for an upload address with POST /v1/files/uploads:

    Terminal window
    curl -H "Authorization: Bearer $OPENBOT_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"filename":"report.pdf","mediaType":"application/pdf","bytes":1048576}' \
    https://api.example.com/v1/files/uploads
    {
    "file": { "id": "file_9a2e…", "status": "pending", "…": "…" },
    "url": "https://s3.example.com/openbot/files/file_9a2e…?X-Amz-Signature=…",
    "method": "PUT",
    "headers": {
    "content-type": "application/pdf",
    "content-length": "1048576"
    },
    "expiresAt": 1793000900000
    }
  2. Send the bytes with PUT to url, with these headers. The address works for 15 minutes. The signature covers the media type and the size, so storage takes no other bytes.

  3. Complete the file with POST /v1/files/:fileId/complete. OpenBot checks that the bytes are in storage with the right size. Then the file is ready.

A file that nobody completes within one hour is deleted.

The platform settings say how large a file can be, and which media types OpenBot takes. By default, a file can have up to 20 MB, and these types are allowed:

  • image/png, image/jpeg, image/gif, image/webp
  • application/pdf
  • text/plain

Each model takes only some types. A file that the model does not take makes the Turn fail. So keep the list to types that your models can read.

A platform admin can also give each member a quota with files.quotaBytes. The quota is the most bytes that the files of one member may take together. Pending files count too, so a direct upload keeps its space before the bytes arrive. A file that does not fit returns 413 with FileQuotaExceeded, with quotaBytes and usedBytes. Delete files to get the space back. By default, there is no quota.


Name a file in the content of a message. input_image takes a file with a media type that starts with image/. input_file takes any file, such as a PDF.

Terminal window
curl -H "Authorization: Bearer $OPENBOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"input": [{
"role": "user",
"content": [
{ "type": "input_text", "text": "What is in this picture?" },
{ "type": "input_image", "file_id": "file_6f1c…" }
]
}]
}' \
https://api.example.com/v1/bots/$BOT/messages

The file must be one of your own files, and it must be ready. If not, OpenBot returns 400 with FileInvalid.

The Chat keeps only the ID of the file, not its bytes. Before each model call, OpenBot reads the bytes from storage. When a file was deleted, the model sees a short note in its place.


Request What it does
GET /v1/files Lists your files, newest first. Use next for more.
GET /v1/files/:fileId Reads one file.
GET /v1/files/:fileId/content Gives the bytes of a ready file.
DELETE /v1/files/:fileId Deletes a file at once. Returns 204.

GET /v1/files/:fileId/content sends the bytes while they come from storage, so a large file does not wait in the memory of OpenBot. When storage fails before the bytes start, the answer is 503. When it fails after that, the answer stops early. Compare the length with bytes of the file to see that you have all of it.

You need read on File to read files, and write on File to upload and delete them. Every member has both for their own files. See Permissions.


OpenBot deletes files that nobody needs. This is garbage collection. Every instance runs it once a minute, and many instances can run it at the same time.

  • A Chat that names a file keeps it. The file stays while the Chat lives.
  • When you delete the Chat, it no longer keeps the file. See Delete the history.
  • A file that no Chat keeps is deleted when nobody used it for a time. The default time is 24 hours. A platform admin can change it with files.unusedMs.
  • A file that nobody completed is deleted after one hour.
  • A file that you delete goes away at once. Its bytes leave storage at the next run.

When there is no storage, OpenBot keeps the rows of deleted files. It removes their bytes when storage comes back.


See File storage.

Status Error When
400 FileInvalid The file is too large, has a type that the platform does not take, or is not ready.
404 FileNotFound You have no file with this ID.
413 FileQuotaExceeded The file does not fit in the space that is left in your quota.
409 FilesDisabled The platform has no storage, or this way of upload is off.
503 FilesUnavailable OpenBot cannot reach its database or the storage.