> ## Documentation Index
> Fetch the complete documentation index at: https://docs.simular.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Upload

> POST /v1/agents/upload

Uploads one file so a message can attach it. The body is the raw file; the name travels in a header.

## Request

```bash theme={null}
curl -s "$SAI_API_URL/v1/agents/upload" \
  -H "Authorization: Bearer $SAI_API_KEY" \
  -H "x-filename: report.pdf" \
  --data-binary @./report.pdf
```

| Header | Required | Notes |
| - | - | - |
| `x-filename` | yes | URL-encoded original file name. The server derives the MIME type from its extension. |

The `Content-Type` header is ignored. Maximum size is 25 MB.

## Response

```json theme={null}
{
  "path": "uploads/report-1790000000000.pdf",
  "name": "report-1790000000000.pdf",
  "mime": "application/pdf",
  "size": 48213,
  "fileId": "f_3kd9"
}
```

Pass this object unchanged as one entry of `attachments` on [`POST /message`](/sai-api/api-reference/message).

## Recognised extensions

`.txt .md .json .js .ts .py .sh .bash .yaml .yml .csv .html .xml .pdf .png .jpg .jpeg .gif .webp .sim`

Anything else is stored as `application/octet-stream`.

## Errors

| Status | Body |
| - | - |
| `400` | `{ "error": "x-filename header is required." }` or an empty body. |
| `409` | `{ "error": "storage_quota_exceeded" }` |
| `413` | `{ "error": "File too large. Maximum is 25MB." }` |
| `429` | More than 30 uploads in an hour. |

## Gotchas

* The returned `name` can differ from the one you sent: unsafe characters are replaced and a timestamp is appended.
* One file per call. Loop for several.
* Use `--data-binary`, not `-d`, so curl does not strip newlines.
