# Files API

> Files Bash makes, and files you hand it.

Send `Authorization: Bearer vk_test_...` on every call.

## `POST /v1/files`

Its own page: [POST /v1/files](https://vestra.ai/developers/reference/api/files/post-v1-files.md)

Upload a file for Bash to use: multipart/form-data with one part named file. user_id in the query names whose Bash it is for; without it, the company's own.

Your API key, scope `runtime` or `all`. On the card: [`files`](https://vestra.ai/developers/files.md). Every call here is a checked sample.

### Request

Query:

- `user_id` (`string`): Whose file it is, by your id for them. Absent: your company's own Bash's.

Headers:

- `Idempotency-Key` (`string`): Send the same key to retry this call safely for 24 hours.

Body, as a form:

- `file` (`string`, required): The file, in a form field named file: 10 MB at most. Limits: at most 10485760 characters.

### Answers 201

- `id` (`string`): The file (file_...): hand it to an ask as an attachment. Example: `file_2nq`.
- `object` (`"file"`): Always file.
- `user_id` (`string | null`): Your id for its user; null on your company's own Bash.
- `filename` (`string | null`): The file's name; null when it has none. Example: `itinerary.pdf`.
- `mime_type` (`string | null`): Its type, such as application/pdf; null when unknown.
- `size_bytes` (`integer | null`): Its size, in bytes; null when unknown.
- `source` (`"upload" | "output"`): upload: a file you handed Bash. output: a file Bash made.
- `task_id` (`string | null`): The task it belongs to (task_...): the one that made it, or used it; null when none did.
- `conversation_id` (`string | null`): The conversation of its task (conv_...); null for a file no task touched.
- `created_at` (`string`): When it was made or uploaded, as an ISO 8601 time.

### Code

**TypeScript**

```ts
const file = await vestra.user('traveller-42').files.upload('ticket.pdf');
```

**Python**

```python
file = vestra.user("traveller-42").files.upload("ticket.pdf")
```

**CLI**

```bash
vestra files add ticket.pdf --user traveller-42
```

**HTTP**

```bash
# Upload a file. Send it for one user as multipart form data, with one part named file, up to 10 MB.
curl "$VESTRA_BASE_URL/v1/files?user_id=traveller-42" \
  -H "Authorization: Bearer $VESTRA_API_KEY" \
  -F "file=@ticket.pdf"

# Download what Bash made. List one conversation's files (its tasks' outputs), or one task's.
curl "$VESTRA_BASE_URL/v1/files?conversation_id=conv_8f2k" \
  -H "Authorization: Bearer $VESTRA_API_KEY"

# Get one file. The response has a download link that works for a short while.
curl "$VESTRA_BASE_URL/v1/files/file_2kq" \
  -H "Authorization: Bearer $VESTRA_API_KEY"
```

**MCP**

```json
{
  "method": "tools/call",
  "params": {
    "name": "files",
    "arguments": { "user": "traveller-42", "conversation": "conv_8f2k" }
  }
}
```

## `GET /v1/files`

Its own page: [GET /v1/files](https://vestra.ai/developers/reference/api/files/get-v1-files.md)

Files, each with its task and conversation: one user's (user_id) or the company's own Bash's, one task's outputs (task_id), or one conversation's, its tasks' outputs (conversation_id). source picks what you handed Bash (upload) or what Bash made (output).

Your API key, scope `runtime` or `all`. On the card: [`files`](https://vestra.ai/developers/files.md). Every call here is a checked sample.

### Request

Query:

- `limit` (`integer`): How many items per page, 1 to 100. Default 20.
- `cursor` (`string`): Where to go on from: the `next_cursor` of the page before, unchanged. Absent: the first page.
- `user_id` (`string`): One user's files, by your id for them. Absent: your company's own Bash's.
- `task_id` (`string`): What one task made (task_...): outputs only.
- `conversation_id` (`string`): One conversation's files, from all its tasks (conv_...).
- `source` (`"upload" | "output"`): Only uploads or only outputs. Default: outputs with task_id or conversation_id, uploads without.

### Answers 200

- `data` (`object[]`): The items on this page.
  - `id` (`string`): The file (file_...): hand it to an ask as an attachment. Example: `file_2nq`.
  - `object` (`"file"`): Always file.
  - `user_id` (`string | null`): Your id for its user; null on your company's own Bash.
  - `filename` (`string | null`): The file's name; null when it has none. Example: `itinerary.pdf`.
  - `mime_type` (`string | null`): Its type, such as application/pdf; null when unknown.
  - `size_bytes` (`integer | null`): Its size, in bytes; null when unknown.
  - `source` (`"upload" | "output"`): upload: a file you handed Bash. output: a file Bash made.
  - `task_id` (`string | null`): The task it belongs to (task_...): the one that made it, or used it; null when none did.
  - `conversation_id` (`string | null`): The conversation of its task (conv_...); null for a file no task touched.
  - `created_at` (`string`): When it was made or uploaded, as an ISO 8601 time.
- `next_cursor` (`string | null`): Send it as `cursor` for the next page; null on the last page.

### Code

**TypeScript**

```ts
const files = await vestra.files.list();
```

**Python**

```python
files = vestra.files.list()
```

**CLI**

```bash
vestra files
```

**HTTP**

```bash
# Upload a file. Send it for one user as multipart form data, with one part named file, up to 10 MB.
curl "$VESTRA_BASE_URL/v1/files?user_id=traveller-42" \
  -H "Authorization: Bearer $VESTRA_API_KEY" \
  -F "file=@ticket.pdf"

# Download what Bash made. List one conversation's files (its tasks' outputs), or one task's.
curl "$VESTRA_BASE_URL/v1/files?conversation_id=conv_8f2k" \
  -H "Authorization: Bearer $VESTRA_API_KEY"

# Get one file. The response has a download link that works for a short while.
curl "$VESTRA_BASE_URL/v1/files/file_2kq" \
  -H "Authorization: Bearer $VESTRA_API_KEY"
```

**MCP**

```json
{
  "method": "tools/call",
  "params": {
    "name": "files",
    "arguments": { "user": "traveller-42", "conversation": "conv_8f2k" }
  }
}
```

## `GET /v1/files/{file_id}`

Its own page: [GET /v1/files/{file_id}](https://vestra.ai/developers/reference/api/files/get-v1-files-file-id.md)

Details and a short-lived download link.

Your API key, or a session's token, scope `runtime` or `all`. On the card: [`files`](https://vestra.ai/developers/files.md). Every call here is a checked sample.

### Request

Path:

- `file_id` (`string`, required): The file's id (`file_...`).

### Answers 200

- `id` (`string`): The file (file_...): hand it to an ask as an attachment. Example: `file_2nq`.
- `object` (`"file"`): Always file.
- `user_id` (`string | null`): Your id for its user; null on your company's own Bash.
- `filename` (`string | null`): The file's name; null when it has none. Example: `itinerary.pdf`.
- `mime_type` (`string | null`): Its type, such as application/pdf; null when unknown.
- `size_bytes` (`integer | null`): Its size, in bytes; null when unknown.
- `source` (`"upload" | "output"`): upload: a file you handed Bash. output: a file Bash made.
- `task_id` (`string | null`): The task it belongs to (task_...): the one that made it, or used it; null when none did.
- `conversation_id` (`string | null`): The conversation of its task (conv_...); null for a file no task touched.
- `created_at` (`string`): When it was made or uploaded, as an ISO 8601 time.
- `download_url` (`string (URL)`): A link to download it: good for 15 minutes, so read the file again for a fresh one.
- `download_expires_at` (`string`): When the link stops working, as an ISO 8601 time.

### Code

**TypeScript**

```ts
const file = await vestra.files.get('file_2kq');
```

**Python**

```python
file = vestra.files.get("file_2kq")
```

**CLI**

```bash
vestra files get file_2kq
```

**HTTP**

```bash
# Upload a file. Send it for one user as multipart form data, with one part named file, up to 10 MB.
curl "$VESTRA_BASE_URL/v1/files?user_id=traveller-42" \
  -H "Authorization: Bearer $VESTRA_API_KEY" \
  -F "file=@ticket.pdf"

# Download what Bash made. List one conversation's files (its tasks' outputs), or one task's.
curl "$VESTRA_BASE_URL/v1/files?conversation_id=conv_8f2k" \
  -H "Authorization: Bearer $VESTRA_API_KEY"

# Get one file. The response has a download link that works for a short while.
curl "$VESTRA_BASE_URL/v1/files/file_2kq" \
  -H "Authorization: Bearer $VESTRA_API_KEY"
```

**MCP**

```json
{
  "method": "tools/call",
  "params": {
    "name": "files",
    "arguments": { "user": "traveller-42", "conversation": "conv_8f2k" }
  }
}
```

## `DELETE /v1/files/{file_id}`

Its own page: [DELETE /v1/files/{file_id}](https://vestra.ai/developers/reference/api/files/delete-v1-files-file-id.md)

Delete it.

Your API key, scope `runtime` or `all`. On the card: [`files`](https://vestra.ai/developers/files.md). Over HTTP it is made from the contract: fill in each {…} and every value.

### Request

Path:

- `file_id` (`string`, required): The file's id (`file_...`).

### Answers 200

- `id` (`string`): The file (file_...).
- `object` (`"file"`): Always file.
- `deleted` (`true`): Always true: it is gone.

### Code

**TypeScript**

```ts
await vestra.files.delete('file_2kq');
```

**Python**

```python
vestra.files.delete("file_2kq")
```

**CLI**

```bash
vestra files delete file_2kq
```

**HTTP**

```bash
curl -X DELETE "$VESTRA_BASE_URL/v1/files/{file_id}" \
  -H "Authorization: Bearer $VESTRA_API_KEY"
```

**MCP**: No sample in your language for this route, so here it is over HTTP.
