
Claude Files API を使ってみる
リテールアプリ共創部の末永です。
Claude API には、ファイルを一度アップロードして file_id で参照できる Files API があります。同じ資料を毎回リクエストに載せ直さずに済み、code execution(code interpreter)ツールの入出力にも使えます。1 年ほど前に追加された機能ですが、あまり触ってこなかったので、今回アップロードから削除までを実際に動かして確認してみます。
Files API でできること
通常のファイル添付ではリクエストごとにファイルの中身を毎回送りますが、Files API では最初の 1 回だけアップロードして、あとは返ってきた file_id を Messages リクエストで参照します。アップロード・一覧・メタデータ取得・削除・ダウンロードといったファイル操作自体は無料で、課金されるのは Messages リクエストで添付した分の入力トークンです。
対応するのは PDF・プレーンテキスト・画像と、コード実行ツールで扱うデータセット類で、ファイルサイズの上限は 1 ファイル 500MB、組織あたり合計 500GB です。
ダウンロードには制限があります。自分でアップロードしたファイルは取得できず、ダウンロードできるのは Claude が生成したファイルだけです。
You can only download files that were created by skills or the code execution tool. Files that you uploaded cannot be downloaded.
(日本語訳:スキルまたはコード実行ツールによって作成されたファイルのみダウンロードできます。ご自身でアップロードしたファイルはダウンロードできません。)
Claude に作らせたファイルを手元に落としたい場合は、code execution ツールと組み合わせます。生成されたファイルが file_id 付きで返るので、それをダウンロードする流れです。今回はアップロード側の確認が目的なので、ここでは扱いません。
データの扱いと保存ポリシー
業務で使う前に気になるのは、アップロードしたファイルがどこにどれくらい保存されるか、という点です。
保存先は Anthropic 側のストレージで、ファイルは API キーのワークスペース単位でスコープされます。同じワークスペースであれば、別のキーからも参照できます。
保存期間に関しては、通常の Anthropic API は入出力を 30 日以内に自動削除しますが、Files API はその例外で、自分で削除するまで残り続けます。機密性の高いファイルを扱うときは、使い終わったら明示的に削除しておいた方が良さそうです。
実際に動かしてみる
検証では TypeScript と公式の @anthropic-ai/sdk を使いました。Files API はベータなので、リクエストに files-api-2025-04-14 のベータ識別子を渡します。
アップロードはファイルを読み込んで渡すだけです。返ってきた ID を以降のリクエストで使い回します。
const uploaded = await client.beta.files.upload({
file: await toFile(
fs.createReadStream("sample/report.txt"),
"report.txt",
{ type: "text/plain" },
),
betas: ["files-api-2025-04-14"],
});
// uploaded.id を以降のリクエストで参照する
アップロード直後のレスポンスがこちらです。downloadable が false になっていて、アップロードしたファイルは落とせない、という先ほどの仕様がここにも表れています。
{
"type": "file",
"id": "file_011CbYiUKCX8XHCpunzWYtb6",
"size_bytes": 849,
"created_at": "2026-05-30T11:59:50.169000Z",
"filename": "report.txt",
"mime_type": "text/plain",
"downloadable": false
}
ちゃんと添付できているかは、file_id を Messages リクエストに載せて要約させると分かります。テキストファイルは document ブロックで参照します。
const message = await client.beta.messages.create({
model,
max_tokens: 512,
betas: ["files-api-2025-04-14"],
messages: [
{
role: "user",
content: [
{ type: "text", text: "添付ファイルの内容を3行以内の箇条書きで日本語要約してください。" },
{ type: "document", source: { type: "file", file_id: uploaded.id } },
],
},
],
});
アップロードした架空のレポートの中身を踏まえた要約が返ってきました。ファイルの内容を読めているので、添付は成立しています。
- 売上好調: 売上高は前年同期比18%増の4.2億円、主力SaaS「Nimbus」が1,250社突破で牽引...
- 新規契約と課題: エンタープライズ契約7件獲得の一方で、北米インフラコスト超過(12%)...
- 次期施策: コスト最適化、オンボーディング自動化、採用チャネル多様化に注力
このあと一覧取得とメタデータ取得でアップロード済みのファイルを確認したあと、念のためダウンロードを試すと、想定どおり 400 で拒否されました。
status = 400
error = {"type":"invalid_request_error",
"message":"File 'file_011CbYiUKCX8XHCpunzWYtb6' is not downloadable"}
最後に削除します。削除レスポンスは file_deleted を返し、削除後に同じ ID でメタデータを取りに行くと 404 になりました。
# DELETE /v1/files/{file_id}
{ "id": "file_011CbYiUKCX8XHCpunzWYtb6", "type": "file_deleted" }
# 削除後に再取得
status = 404
error = {"type":"not_found_error",
"message":"File `file_011CbYiUKCX8XHCpunzWYtb6` not found."}
余談ですが、アップロード自体は拡張子や mimeType をほとんど問わず通りました。中身がテキストのファイルを application/pdf として送っても、mimeType を省いても(その場合は application/octet-stream になります)成功します。型の不一致は document や image ブロックで参照した時点でチェックされるようです。
最後に
正直なところ、1 回のやり取りで終わるなら毎回インラインで添付すれば足りてしまうので、Files API の出番はそこまで多くありません。同じファイルを複数のリクエストで使い回したいときや、code execution ツールと組み合わせて入出力をやり取りするときが、主な使いどころになりそうです。後者はまだ試せていないので、別の機会に動かしてみようかなぁと思います。
では👋







