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

# Upload a file (response URL)

> Upload a file mid-workflow with nothing but the response_url. No API key needed.

Upload through the token that is already in your event. Best mid-workflow, in n8n or Make, where the `response_url` is already mapped and there is no key to manage. Read back `file.file_id`, then use it in an [`image`](https://docs.my-aichatbot.com/block-kit/blocks/image), [`file`](https://docs.my-aichatbot.com/block-kit/blocks/file) or [`card`](https://docs.my-aichatbot.com/block-kit/blocks/card) block.

## Path parameters

**token** `string` *required*

The token baked into the event's `response_url`. The upload URL is that URL plus `/files`.

## Body

`multipart/form-data`.

**file** `file` *required*

The file itself. Missing it returns `400 MALFORMED_MULTIPART`.

**filename** `string`

Replaces the file's own name. Cut to 255 characters.

## Response

**ok** `boolean`

`true` on success.

**file** `object`

The stored file.

**properties**

**file\_id** `string`

Use this in a block.

**name** `string`

The stored name.

**size\_bytes** `number`

The stored size, after any image conversion.

**mime\_type** `string`

Found by reading the file's first bytes.

**expires\_at** `string | null`

Always `null` for now.

```bash curl theme={null}
curl -X POST "$RESPONSE_URL/files" \
  -F "file=@june-report.pdf" \
  -F "filename=june-report.pdf"
```

```javascript Node.js theme={null}
import { readFile } from 'node:fs/promises'

const form = new FormData()
form.append('file', new Blob([await readFile('june-report.pdf')]), 'june-report.pdf')

const res = await fetch(`${responseUrl}/files`, { method: 'POST', body: form })
const { file } = await res.json()
```

```python Python theme={null}
import requests

with open("june-report.pdf", "rb") as f:
    res = requests.post(f"{response_url}/files", files={"file": f})

file = res.json()["file"]
```

```json 201 Created theme={null}
{
  "ok": true,
  "file": {
    "file_id": "6f1c2a84",
    "name": "june-report.pdf",
    "size_bytes": 482113,
    "mime_type": "application/pdf",
    "expires_at": null
  }
}
```

```json 422 Blocked type theme={null}
{
  "ok": false,
  "error": { "code": "FILE_TYPE_BLOCKED", "message": "This file type is not allowed." }
}
```

## What we accept

Images (PNG, JPEG, GIF, WebP, AVIF) up to 10 MB, everything else up to 25 MB. We read the file's first bytes to decide what it is; the name and `Content-Type` are never trusted. Images are converted to WebP and only that copy is kept. Programs and HTML are blocked, and HEIC is refused. Full detail in [Sending files](https://docs.my-aichatbot.com/sending-messages/files.md).

## Errors

| Status | Code | Meaning |
| - | - | - |
| `400` | `MALFORMED_MULTIPART` | Not `multipart/form-data`, or no `file` part. |
| `401` | `token_invalid` | The token is broken or has a bad signature. |
| `402` | `STORAGE_CAP_REACHED` | Workspace storage is full. Nothing was saved. |
| `410` | `RESPONSE_URL_EXPIRED` | Past 45 minutes. Use [Upload a file (API key)](https://docs.my-aichatbot.com/api-reference/upload-file.md) instead. |
| `413` | `FILE_TOO_LARGE` | Over 10 MB (image) or 25 MB (other). |
| `415` | `IMAGE_FORMAT_UNSUPPORTED` | HEIC. |
| `422` | `FILE_TYPE_BLOCKED` | A program or HTML file. |
| `429` | `rate_limited` | Over 20 uploads per minute for this conversation. Wait for `retry_after` seconds. |
| `500` | `UPLOAD_FAILED` | We could not store the file. Safe to retry. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.