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

# Files API — upload and retrieve attachments

> Upload file attachments via POST /api/upload and retrieve them via GET /api/files/:key. Files are private to your account and served through a secure proxy.

The files API handles file attachments for notes. You upload a file to receive a URL, then include that URL in your note's Markdown. Files are served through a secure proxy and are never publicly accessible — only authenticated owners can retrieve their files.

<Warning>
  File URLs are private. Only the authenticated owner can access files. Never expose file URLs publicly.
</Warning>

***

## POST /api/upload

Upload a file attachment. The request must use `multipart/form-data` encoding.

### Request

**Content-Type:** `multipart/form-data`

<ParamField body="file" type="file" required>
  The file to upload. Passed as a form field named `file`.
</ParamField>

### Response

**201 Created** — returns metadata about the uploaded file including the URL to reference in Markdown.

<ResponseField name="filename" type="string" required>
  The original filename of the uploaded file.
</ResponseField>

<ResponseField name="url" type="string" required>
  Internal proxy URL of the form `/api/files/{userId}/{uuid}.{ext}`. Use this in your note's Markdown.
</ResponseField>

<ResponseField name="mime_type" type="string" required>
  MIME type of the file, e.g. `"image/png"`, `"application/pdf"`.
</ResponseField>

<ResponseField name="size_bytes" type="number" required>
  File size in bytes.
</ResponseField>

```bash theme={null}
curl -X POST https://your-spote-app.com/api/upload \
  -H "Authorization: Bearer spote_YOUR_TOKEN" \
  -F "file=@screenshot.png"
```

```json theme={null}
{
  "filename": "screenshot.png",
  "url": "/api/files/user_abc123/f47ac10b-58cc-4372-a567-0e02b2c3d479.png",
  "mime_type": "image/png",
  "size_bytes": 45231
}
```

### Using the URL in Markdown

Include the returned `url` directly in your note's Markdown using standard image or link syntax:

```markdown theme={null}
![Screenshot](/api/files/user_abc123/f47ac10b-58cc-4372-a567-0e02b2c3d479.png)
```

When you save the note via `POST /api/notes` or `PUT /api/notes/:id`, include the attachment in the `text` field. Spote stores the URL in the note's `attachments` array automatically.

***

## GET /api/files/:key

Retrieve and stream a file. The server validates that the authenticated user owns the file before serving it.

### Path parameters

<ParamField path="key" type="string" required>
  The file key, which is the path segment from the upload response URL after `/api/files/`. For example, if the upload URL is `/api/files/user_abc123/uuid.png`, the key is `user_abc123/uuid.png`.
</ParamField>

### Response

**200 OK** — streams the file content with the correct `Content-Type` header. The response includes `Cache-Control: private, max-age=3600`.

**403 Forbidden** — the key does not belong to the authenticated user.

**404 Not Found** — the file does not exist in storage.

```bash theme={null}
curl "https://your-spote-app.com/api/files/user_abc123/f47ac10b-58cc-4372-a567-0e02b2c3d479.png" \
  -H "Authorization: Bearer spote_YOUR_TOKEN" \
  --output screenshot.png
```
