Skip to main content

Claude API Files API Guide: Upload, Reference, and Manage Files

A step-by-step guide to uploading files to the Claude API's Files API and reusing them by file_id across Messages requests, covering formats, expiration, and management.

By
🌐 This article was machine-translated and may contain inaccuracies. Read the Korean original if in doubt.

The Claude API's Files API — a way to upload a file once and keep reusing it across requests by its file_id (a unique identifier returned when you upload) — lets you skip re-attaching the same document or image to every request. The Files API was once a beta feature, but it's now generally available with no separate beta flag required. Rather than covering that announcement itself, this guide focuses on the practical steps: uploading a file and pulling it into Messages API requests.

🟢 Model references match the current lineup · model notice · Fable subscription
🟢 Model references match the current lineup · Claude Opus 5.5 / Claude Sonnet 5 / Claude Haiku 4.5 (higher tier: Claude Fable 5.1). This notice changes only when Anthropic ships a new model.

Fable 5 and 5.1 subscription (updated September 7, 2026): Claude Fable 5.1, released September 1, 2026, is the current Fable model and Fable 5 is now legacy. Plan terms are the same for both — Max and Team Premium plans include Fable at up to 50% of the weekly usage limit; Pro and Team Standard use usage credits (

🟢 Model references match the current lineup · Claude Opus 5.5 / Claude Sonnet 5 / Claude Haiku 4.5 (higher tier: Claude Fable 5.1). This notice changes only when Anthropic ships a new model.
0/M input, $50/M output tokens). The one-time
🟢 Model references match the current lineup · Claude Opus 5.5 / Claude Sonnet 5 / Claude Haiku 4.5 (higher tier: Claude Fable 5.1). This notice changes only when Anthropic ships a new model.
00 credit applied only to the Fable 5 transition and is not offered for 5.1. Some coding and debugging requests may be answered by an Opus model due to a security classifier (both models). See the Fable 5.1 guide and the Fable 5 availability guide for details.

① Upload file POST /v1/files ② Get file_id Save the id from the response ③ Messages request Reference by file_id Reusable many times

What can you do with the Files API?

The Files API lets you upload a file once and then reference it across many Messages requests using only its file_id. It supports four main operations: uploading a file to receive a unique file_id, referencing that file_id in Messages API requests instead of resending the content, downloading files created by the code execution tool or skills, and managing files through listing, retrieving, and deleting.

Note: uploaded files are accessible to your entire workspace, not scoped to a single user or conversation. Any API key in the same workspace can reference the same file. Never accept file_id values from end users or pass them through untrusted input — one user could end up reading a file another user uploaded. Keep the mapping between your users and their files on your own server.

What you need before you start

A few things need to be in place before you can use the Files API.

  • A Claude API key — issued from the Claude Console. Setting it as the ANTHROPIC_API_KEY environment variable (a value stored for your terminal session) saves you from re-entering it on every request.
  • The anthropic-version header — required on every API request; the examples below use 2023-06-01.
  • A tool to send requests — curl (a command-line tool for sending web requests) works for quick tests; for a real application, use an official SDK (software development kit — a language-specific library that wraps API calls) such as the Python or TypeScript one.

Step 1: Upload a file

Upload by sending a request to POST https://api.anthropic.com/v1/files. With curl:

FILE_ID=$(curl -X POST https://api.anthropic.com/v1/files \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -F "file=@/path/to/document.pdf" | jq -r '.id')
echo "$FILE_ID"

The -F flag attaches the file as multipart/form-data (a standard way to send binary data like files alongside text fields). A successful request returns a JSON response like this:

{
  "id": "file_011CNha8iCJcU1wXNR6q4V8w",
  "type": "file",
  "filename": "document.pdf",
  "mime_type": "application/pdf",
  "size_bytes": 1024000,
  "created_at": "2025-01-01T00:00:00Z",
  "downloadable": false,
  "expires_at": null
}

This means it worked: the response contains an id starting with file_ — that's your upload's file_id, and it's what you'll reference from now on. downloadable is always false for files you upload yourself (you can't download them back), and expires_at stays null unless you set an expiration.

Step 2: Reference the uploaded file in a Messages request

messages: [ { role: "user", content: [ ... ] } ] type: "text" text: "Summarize this document" type: "document" source: { type: "file", file_id: "file_011C..." } Use the file_id returned at upload time

To use an uploaded file, add a block referencing its file_id inside the content array (the list holding a message's content) of a Messages API request. For PDFs and text files, use a document block:

{
  "model": "claude-opus-5",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": [
        { "type": "text", "text": "Please summarize this document for me." },
        {
          "type": "document",
          "source": { "type": "file", "file_id": "file_011CNha8iCJcU1wXNR6q4V8w" }
        }
      ]
    }
  ]
}

For images, use an image block with the same file_id pattern. To send a file to the code execution tool (a tool that lets the model run Python or bash code to analyze data), use a container_upload block with the file_id. In all three cases, you send only the file_id — not the file content itself — with every request.

Supported file types

The Files API supports different file types, each mapped to a specific content block type.

File typeMIME typeContent block typeUse case
PDFapplication/pdfdocumentText analysis, document processing
Plain texttext/plaindocumentText analysis, processing
Imagesimage/jpeg, image/png, image/gif, image/webpimageImage analysis, visual tasks
Datasets and other formatsVariescontainer_uploadAnalyze data, create visualizations via the code execution tool

Note: formats not in this table, such as .docx and .xlsx, can't be used directly with a document block. Convert them to plain text or PDF first. Files that are already plain text, like .csv and .md, can either be inlined directly into a message or uploaded through the Files API with an explicit text/plain content type. If a .docx file contains images, converting it to PDF first lets you use PDF support's built-in image parsing, including citations.

Setting file expiration

To have a file expire automatically, include an expires_in_seconds form field when uploading. It must be an integer between 3,600 (1 hour) and 7,776,000 (90 days). If you don't set it, the response's expires_at stays null and the file doesn't auto-expire.

Once a file reaches its expires_at:

  • Downloading its content (GET /v1/files/{file_id}/content) returns a 404 error.
  • A Messages request referencing the file fails before inference runs.
  • Its metadata (GET /v1/files/{file_id}) stays readable for up to 30 days after expiration, and it still appears in list responses during that window — compare expires_at to the current time to filter it out.

Note: expiration is set once at upload time and can't be changed afterward. To remove a file sooner, delete it directly with DELETE /v1/files/{file_id} instead of waiting for it to expire. Deleted files can't be recovered.

Listing, retrieving, deleting, and downloading files

Manage uploaded files through listing, metadata retrieval, deletion, and conditional download.

  • List files — GET /v1/files is paginated (20 files by default, up to 1,000, newest first). Pass the response's next_page cursor back as the page parameter to fetch the next page. To check a known set of files instead, pass up to 100 IDs as ids[] query parameters — this can't be combined with page or limit, and any ID that doesn't resolve is silently omitted from the results.
  • Get file metadata — GET /v1/files/{file_id} retrieves information about a single file.
  • Delete a file — DELETE /v1/files/{file_id} removes it from your workspace.
  • Download a file — GET /v1/files/{file_id}/content. However, files you upload yourself can't be downloaded. Only files with downloadable: true in their metadata — those created by skills or the code execution tool — can be downloaded. Trying to download a file you uploaded returns a 400 error.

Common errors and how to fix them

These are the errors you're most likely to run into with the Files API, along with their causes and fixes.

ErrorCauseFix
404 File not foundThe file_id doesn't exist or you don't have access to itCheck the file_id for typos, and whether the file was deleted or expired
400 Invalid file typeThe file type doesn't match the content block type (e.g., an image used in a document block)Switch to the block type matching the file's format
400 Not downloadableTrying to download a file you uploaded yourselfOnly files created by skills or the code execution tool can be downloaded
400 Exceeds context window sizeThe file is larger than the model's context windowSplit the file or reduce its size
400 Invalid filenameThe filename is outside 1-255 characters or has forbidden charactersCheck and fix the filename
413 File too largeThe file exceeds the 500 MB limitReduce the file's size
400 Storage limit exceededYour organization has reached the 1 TB storage limitDelete unneeded files, then retry

Storage limits and pricing

The Files API allows up to 500 MB per file and up to 1 TB total per organization. File management operations themselves — uploading, downloading, listing, retrieving metadata, and deleting — are free. File content that's actually used in a Messages request is billed as input tokens (the unit used to measure how much text or image data goes into the model). File-related API calls are rate-limited to roughly 500 requests per minute; contact sales for a higher limit.

Frequently asked questions

Q. Can I download a file after I've uploaded it?
No, files you upload yourself can't be downloaded. Only files with downloadable set to true in their metadata — created by skills or the code execution tool — can be downloaded. Trying to download a file you uploaded returns a 400 error.

Q. How long is a file kept if I don't set an expiration?
If you don't set expires_in_seconds, expires_at stays null and the file doesn't auto-expire — it's kept until you explicitly delete it with a DELETE request.

Q. Can I use .docx or .xlsx files directly with the Files API?
No, the document block only supports PDF and plain text. Convert .docx and .xlsx files to plain text or PDF before using them.

Q. Are file uploads and downloads billed like tokens?
No, file management operations — uploading, downloading, listing, and deleting — are free. Only file content actually used in a Messages request is billed, as input tokens.

Once you have the upload-reference-manage flow down, you can reuse the same file across requests with just a file_id instead of resending it each time. The main things to keep in mind are setting expiration deliberately and remembering that file access is scoped to your whole workspace.

Was this helpful?

Keep reading