# 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
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
{
  "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`](/documentation/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.
