Documents and media
Send PDFs, Office files, images, audio and video in a conversation; what each becomes, and what it costs.
Documents
Any chat model can read a document: the API turns it into text before the model sees it, so the model needs no file support of its own. PDF, Word, Excel, PowerPoint, RTF, HTML, CSV, Markdown, JSON, XML and plain text are read.
| Route | Part | Holds |
|---|---|---|
/v1/chat/completions |
file |
A filename, and the file as file_data (a data URI, bare base64 or a URL) or file_id |
/v1/responses |
input_file |
A filename, and the file as file_data, file_url or file_id |
/v1/messages |
document |
A source: base64, a URL, text or a file_id |
# A document travels as a data URI; the API turns it into text the model reads
doc=$(printf '# Leave policy\n\nNew hires get 20 vacation days a year.\n' | base64 | tr -d '\n')
curl https://api.vultrinference.com/v1/chat/completions \
-H "Authorization: Bearer $VULTR_INFERENCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4.1-flash",
"messages": [{"role": "user", "content": [
{"type": "text", "text": "How many vacation days do new hires get?"},
{"type": "file", "file": {"filename": "policy.md", "file_data": "data:text/markdown;base64,'"$doc"'"}}
]}]
}'import base64
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.vultrinference.com/v1", api_key=os.environ["VULTR_INFERENCE_API_KEY"])
# A PDF, Word, Excel or PowerPoint file works the same way: read its bytes and name its type
policy = base64.b64encode(b"# Leave policy\n\nNew hires get 20 vacation days a year.\n").decode()
reply = client.chat.completions.create(
model="deepseek-v4.1-flash",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "How many vacation days do new hires get?"},
{"type": "file", "file": {"filename": "policy.md", "file_data": f"data:text/markdown;base64,{policy}"}},
],
}],
)
print(reply.choices[0].message.content)The type comes from the data URI, then the filename's extension, then the file's first bytes. If none of them tells it, the answer is a 400 that asks you to name the file.
- The text counts toward the context window, and is billed as prompt tokens in every request that sends it.
- A file may be up to 100 MB, and a PDF up to 300 pages.
- A long PDF takes about half a second a page to read. If your request gives up partway, the conversion still finishes, and the same document sent within the hour is not read again.
- When the converter is busy the answer is 503; retry after
Retry-After.
To use one document in many requests, upload it once to POST /v1/files and send its file_id: it is read once, up front. Chat over your files shows the whole round.
Images, audio and video
On /v1/chat/completions, a model that reads a kind of media gets it as it is. A model that does not gets a description of it, written by a model that does, so it can still answer about it.
| Media | Part | Takes | A model that reads it gets |
|---|---|---|---|
| Images | image_url |
A data URI or an https URL |
The picture, fitted to 768 by 768 pixels |
| Audio | input_audio |
Up to an hour | The clip |
| Video | video_url |
Up to two minutes | The clip, at one frame a second |
A model's catalog entry lists audio or video among its inputs when it hears or watches them itself. /v1/responses and /v1/messages pass media to the model as it is, without descriptions, so use a model that reads it.
Errors
| Status | When |
|---|---|
| 400 | The file is unreadable, encrypted or empty, a PDF is over 300 pages, a URL could not be downloaded, or the type could not be told. The message says which. |
| 400 | A file_id that does not exist, is still processing, failed to convert, or has expired. |
| 503 | The converter is busy. Retry after Retry-After. |
Endpoints