> ## 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 (API key)

> Upload a file for your bot — no conversation and no time limit.

Upload against the bot itself — no conversation, no time limit. Use it when the `response_url` has expired, or to prepare a file ahead of time.

## Authorization

<ParamField header="Authorization" type="string" required>
  `Bearer mac_live_…`
</ParamField>

## Path parameters

<ParamField path="chatbot_id" type="string" required>
  Must match the bot your key belongs to, or you get `403 wrong_chatbot`.
</ParamField>

## Body

`multipart/form-data`.

<ParamField body="file" type="file" required>
  The file itself.
</ParamField>

<ParamField body="filename" type="string">
  Replaces the file's own name.
</ParamField>

## Response

<ResponseField name="ok" type="boolean">
  `true` on success.
</ResponseField>

<ResponseField name="file" type="object">
  The stored file.

  <Expandable title="properties">
    <ResponseField name="file_id" type="string">
      Use this in a block.
    </ResponseField>

    <ResponseField name="name" type="string">
      The stored name.
    </ResponseField>

    <ResponseField name="size_bytes" type="number">
      The stored size, after any image conversion.
    </ResponseField>

    <ResponseField name="mime_type" type="string">
      Found by reading the file's first bytes.
    </ResponseField>

    <ResponseField name="expires_at" type="string | null">
      Always `null` for now.
    </ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
  ```bash curl theme={null}
  curl -X POST "https://app.my-aichatbot.com/api/v1/bots/$CHATBOT_ID/files" \
    -H "Authorization: Bearer $MAC_KEY" \
    -F "file=@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(
    `https://app.my-aichatbot.com/api/v1/bots/${chatbotId}/files`,
    {
      method: 'POST',
      headers: { Authorization: `Bearer ${process.env.MAC_KEY}` },
      body: form
    }
  )

  const { file } = await res.json()
  ```

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

  with open("june-report.pdf", "rb") as f:
      res = requests.post(
          f"https://app.my-aichatbot.com/api/v1/bots/{chatbot_id}/files",
          headers={"Authorization": f"Bearer {os.environ['MAC_KEY']}"},
          files={"file": f},
      )

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

  ```php PHP theme={null}
  $ch = curl_init("https://app.my-aichatbot.com/api/v1/bots/{$chatbotId}/files");
  curl_setopt_array($ch, [
      CURLOPT_POST => true,
      CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('MAC_KEY')],
      CURLOPT_POSTFIELDS => [
          'file' => new CURLFile('june-report.pdf', 'application/pdf', 'june-report.pdf'),
      ],
      CURLOPT_RETURNTRANSFER => true,
  ]);
  $file = json_decode(curl_exec($ch), true)['file'];
  ```

  ```go Go theme={null}
  var buf bytes.Buffer
  w := multipart.NewWriter(&buf)

  part, _ := w.CreateFormFile("file", "june-report.pdf")
  f, _ := os.Open("june-report.pdf")
  io.Copy(part, f)
  w.Close()

  req, _ := http.NewRequest("POST",
      "https://app.my-aichatbot.com/api/v1/bots/"+chatbotID+"/files",
      &buf)
  req.Header.Set("Authorization", "Bearer "+os.Getenv("MAC_KEY"))
  req.Header.Set("Content-Type", w.FormDataContentType())

  resp, err := http.DefaultClient.Do(req)
  ```
</RequestExample>

<ResponseExample>
  ```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 403 Wrong bot theme={null}
  {
    "ok": false,
    "error": { "code": "wrong_chatbot", "message": "This key belongs to a different bot." }
  }
  ```
</ResponseExample>

## Errors

| Status | Code                            |
| ------ | ------------------------------- |
| `400`  | `MALFORMED_MULTIPART`           |
| `401`  | `invalid_api_key`               |
| `402`  | `STORAGE_CAP_REACHED`           |
| `403`  | `wrong_chatbot`                 |
| `413`  | `FILE_TOO_LARGE`                |
| `415`  | `IMAGE_FORMAT_UNSUPPORTED`      |
| `422`  | `FILE_TYPE_BLOCKED`             |
| `429`  | `rate_limited` (20/min per bot) |
