Skip to content

Upload a file

POST /v1/files

Uploads one file to the Drive of the user who owns the key.

Send multipart/form-data with one file field, whose part includes a filename, and optionally an expires_in_seconds field. The server accepts any file type. In a body over 10 MiB, expires_in_seconds must come before file. The Python and .NET SDKs send it first. With the TypeScript SDK, write expires_in_seconds before file in the object you pass to files.upload.

These limits apply:

  • A file can be up to your deployment’s upload limit, which is 5 GiB unless your administrator set it lower.
  • Send a Content-Length header. cURL and the SDKs send one for you. A request without one must use chunked encoding and be 10 MiB or smaller.
  • Each key can have up to 4 uploads in progress on one server instance, and each instance takes up to 8 in total across all keys. Keep 4 or fewer uploads in progress, and retry on 429.

If the request fails partway, the server keeps nothing.

The key must have the files:write capability. For what each capability allows, see Keys.

Body (multipart/form-data)

NameTypeRequiredDefaultDescription
filebinaryYesThe file, with a filename. If the part has no media type, the server stores the file as application/octet-stream.
expires_in_secondsintegerNoThe number of seconds until the file expires on Anthropic’s API. Must be a whole number between 3600 and 7776000. It isn’t applied: the file is kept until you delete it, and the file object has no expires_at.

Response

Returns 200 with the file object. For every field, see Files.

{
"id": "329409ba-f288-4b44-9c73-14a18150edee",
"created_at": "2026-10-21T01:41:11.028Z",
"filename": "cities.csv",
"mime_type": "text/csv",
"size_bytes": 46,
"type": "file",
"downloadable": true
}

Errors

This endpoint can return these errors as well as the common errors.

Statuserror.typeCause and fix
400invalid_request_errorThe form has a field other than file and expires_in_seconds. Remove the other fields.
400invalid_request_errorexpires_in_seconds isn’t a whole number between 3600 and 7776000. Send a value in that range, or omit it.
400invalid_request_errorexpires_in_seconds comes after file in a body over 10 MiB. Send expires_in_seconds before file, or omit it.
400invalid_request_errorThe form has no file field, or more than one, or the filename is empty. Send exactly one file field with a non-empty filename.
400invalid_request_errorThe body doesn’t match its Content-Length: bytes follow the closing boundary, or the body ends early. The server keeps nothing. Send an exact Content-Length.
413request_too_largeThe file is over your deployment’s upload limit (5 GiB unless your administrator set it lower), or a chunked request is over 10 MiB. The message gives the limit. If the file is over the upload limit, send a smaller file. If the request is chunked and over 10 MiB, send it again with a Content-Length header.
429rate_limit_errorThis key already has 4 uploads in progress on the server instance that answered, or 8 are in progress there for all keys. Wait for the time in Retry-After, then retry.

Example

cURL
curl -sS -X POST "$CONTEXT_BASE_URL/v1/files" -H "x-api-key: $CONTEXT_API_KEY" -F "file=@cities.csv;type=text/csv"
Python
from pathlib import Path
uploaded = client.beta.files.upload(file=Path("cities.csv"))
print(uploaded.id)
TypeScript
import { readFile } from "node:fs/promises"
import { toFile } from "@anthropic-ai/sdk"
const uploaded = await client.beta.files.upload({ file: await toFile(await readFile("cities.csv"), "cities.csv", { type: "text/csv" }) })