Concepts
Files
A file is something you upload for a task to work with, or something a task made, and you can download both.
Work often starts with a file, such as a spreadsheet to read or a PDF to summarize, and often ends with one, such as a report a worker wrote. The Files API holds both. You upload a file once, give it to as many tasks as you like, and download what a task made.
One store holds every file of a workspace: what you upload and what tasks make. Each has an id that starts with file_. This page explains how a file gets to a task, how to get one back, the size limits, and when a file is kept or goes.
What a file holds
| Field | What it is |
|---|---|
id |
The file's id: file_ and 32 characters. |
filename |
Up to 255 characters. |
mime_type |
What the file is, such as application/pdf. |
size_bytes |
The size of the file. |
created_at |
When the file was made. |
downloadable |
Always true. An uploaded file can be downloaded here. In Claude Managed Agents it cannot. |
expires_at |
When the file expires, or null when it does not. |
scope |
null for a file you uploaded or kept. { "type": "task", "id" } for a file a task made. |
Upload a file
POST /files takes a multipart form with one file part, and optionally expires_in_seconds. Send one file in each upload. The answer is the file.
curl https://core.thelittleworker.com/api/v1/files \
-H "x-api-key: $LITTLE_WORKER_API_KEY" \
-H "Little-Worker-Version: 2026-10-19" \
-F "[email protected];type=text/csv" \
-F "expires_in_seconds=86400"- Size. A file is at most 500 MB (500,000,000 bytes), and a workspace keeps at most 1 TB of files. A larger file, or an upload into a full workspace, is
413witherror.typerequest_too_large. The 10 MiB limit on other requests does not apply to an upload. - Expiry.
expires_in_secondsis a whole number from 3,600 (one hour) to 7,776,000 (90 days). Left out, the file does not expire. An expired file's content is gone at once, and its record stays readable for 30 days more. - Name and type. The name is trimmed and cut to 255 characters. A blank name becomes
file. The type comes from the part's content type, or isapplication/octet-stream.
Give a file to a task
A file reaches a task as a resource. Name it when you give the task, in resources:
{ "type": "file", "file_id": "file_8d4b2f6a0e1c4973a5d8c3e7b9f10264" }You can add one later with POST /tasks/{task_id}/resources and the same body. A file can be on a task once: a second time is 400. An expired file cannot be given: upload it again.
The task's resource has its own id, which starts with resource_. It also has a mount_path, which is where the file sits on the task's computer, under the task's own folder. Little Worker sets it, and you can only send null. List a task's resources with GET /tasks/{task_id}/resources, and take a file off with DELETE /tasks/{task_id}/resources/{resource_id}. A task and a routine can take up to 100 resources of all kinds. A routine copies its resources onto each task it makes.
There are two other ways to put a file in front of a worker:
- In a message. A
user.messagecan carryimageanddocumentblocks with the bytes inline, as base64 or plain text. One message holds at most 6 images and documents, and a request body is at most 10 MiB. Afileorurlsource in a message block is400for now. - As a rubric. A task's outcome can use a file as its
rubric, with{ "type": "file", "file_id" }.
Get a file back
A file a task made has a scope of { "type": "task", "id" }. List a task's files with GET /files?scope_id= and the task's id. GET /files lists them all, newest first, and GET /files/{file_id} reads one.
GET /files/{file_id}/content downloads the bytes. It answers with the file's own content type and a content-disposition of attachment. An expired file, or one whose content is gone, is 404.
Keep a file after history goes
A task's history is not kept forever on every plan, and the files a task made go with it. Keep a file to hold on to it. POST /files/{file_id}/keep turns a file a task made into a saved file with no task scope, so it lasts after the task's history goes. Keeping an upload, or a file you already kept, answers the file as it is.
When a file goes depends on how it was made. You can tell by its scope.
| How the file was made | scope |
When it is deleted |
|---|---|---|
Uploaded with POST /files |
null |
Never by a purge. By DELETE /files/{file_id}, or at its expires_at if you set one. A purged message that named it loses only the link. |
| Made by a task | { "type": "task", "id" } |
With the task's history: by the free plan's purge after 7 days, or by DELETE /tasks/{task_id}. Not if you keep it first. |
| Made by a task, then kept | null |
Only by DELETE /files/{file_id}. |
| Attached to a chat message in the app, with no upload through the Files API | None | With its message, when the message is purged. |
DELETE /files/{file_id} removes a file and answers { "type": "file_deleted", "id" }. The bytes go too, unless another file still holds the same content. Copies in Little Worker's nightly backups are erased within 31 days after that.
A purge on the free plan removes the files a task made along with the rest of its work, but it keeps your uploaded files and the files you kept. Paid plans keep history until you delete it. See Tasks.
Limits
| What | Limit |
|---|---|
| One file | 500 MB |
| Files in a workspace | 1 TB in all |
| Files in one upload | 1 |
expires_in_seconds |
3,600 to 7,776,000 |
| After a file expires | Its record is readable for 30 more days |
| Name | 255 characters |
| Resources on a task | 100, of all kinds |
| Images and documents in one message | 6 |
| Any other request body | 10 MiB |