2026-06-08
If you're sending the same document to Claude repeatedly — a policy PDF, a data dictionary, a client CSV — you're probably re-uploading it on every API call. That's wasteful, and it adds latency every single time.
Files API — a separate Anthropic endpoint that stores a file on Anthropic's servers and gives you back an ID. You then pass that ID in your message instead of the raw file bytes.
Base64 — a way of encoding binary files (like PDFs) as plain text so they can travel inside a JSON payload. Without the Files API, this is how you'd send a PDF to Claude.
Multipart upload — how browsers and HTTP clients send files: the file travels as its own chunk in the request body, rather than being encoded into JSON.
The Files API breaks the upload step away from the inference step. You upload a file once, get an ID back, and then reference that ID in as many API calls as you like — for up to 30 days. The file lives on Anthropic's side. Your subsequent calls are just JSON with a short string.
This matters most when: - You're building a multi-turn workflow that references the same document throughout. - You're running batch analysis across many prompts against the same source file. - Your file is large enough that base64-encoding it bloats every request payload noticeably.
Step 1 — upload the file (once):
import anthropic
client = anthropic.Anthropic()
with open("report.pdf", "rb") as f:
response = client.beta.files.upload(
file=("report.pdf", f, "application/pdf"),
)
file_id = response.id
print(file_id) # e.g. "file_abc123xyz"
Step 2 — use the ID in any subsequent call:
message = client.beta.messages.create(
model="claude-opus-4-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {
"type": "file",
"file_id": file_id,
},
},
{
"type": "text",
"text": "Summarise the key findings in this report."
}
],
}
],
betas=["files-api-2025-04-14"],
)
You can reuse file_id across sessions, scripts, and different prompts — no re-uploading needed.
To clean up when you're done: client.beta.files.delete(file_id).
Use it when the same file appears in more than one API call. Use it when your files are large and the base64 overhead is noticeable. Use it in any agentic pipeline where a document is a fixed reference rather than dynamic input.
Skip it for one-off calls where you'll never reuse the file. Also skip it if the content changes between calls — the Files API stores a snapshot, so a CSV that updates daily needs a fresh upload each time.
Take any script you have that sends a PDF or CSV to Claude. Pull out the file-loading logic, run the upload step separately, print the file_id, and store it. Then rewrite the main call to use "type": "file" with that ID. Time both versions — the difference in request size and latency will be immediately visible.
Don't miss what's next. Subscribe to My Claude Daily Learning: