# 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.

```bash
curl https://core.thelittleworker.com/api/v1/files \
  -H "x-api-key: $LITTLE_WORKER_API_KEY" \
  -H "Little-Worker-Version: 2026-10-19" \
  -F "file=@sales.csv;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 `413` with `error.type` `request_too_large`. The 10 MiB limit on other requests does not apply to an upload.
- **Expiry.** `expires_in_seconds` is 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 is `application/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`:

```json
{ "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.message` can carry `image` and `document` blocks 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. A `file` or `url` source in a message block is `400` for 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](/concepts/tasks#how-long-a-task-is-kept).

## 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 |

## Next steps

- [Tasks](/concepts/tasks): how `resources` is set when you give a task, and how history is kept.
- [Computers](/concepts/computers): where a file sits on the computer a task works on.
- [Memory](/concepts/memory): notes that last from task to task, when a file is too much.
