# Documents – API reference

> Stored files with their AI analysis: search, upload, download.

Stored files with their AI analysis: search, upload, download.

## List and search documents

**`GET https://api.lifebutler.io/v1/workspaces/{workspaceId}/documents`** · scope `documents:read` · MCP tool `list_documents`

Newest first. With q, a text search over title, file name, notes, category and the AI analysis (summary, issuer, key content, tags); every word must match, accents and case don't matter. For questions in natural language use search or ask_butler.

### Path

| Field | Type | Description |
|---|---|---|
| `workspaceId` | string | Workspace id (from list_workspaces). |

### Query

| Field | Type | Description |
|---|---|---|
| `q` | string | Words to find, e.g. "stadtwerke 2026". |
| `category` | `invoice` \| `contract` \| `insurance` \| `bank` \| `tax` \| `payslip` \| `medical` \| `school` \| `authority` \| `warranty` \| `receipt` \| `letter` \| `other` |  |
| `limit` | integer | Maximum number of results (1–100, default 25). Default: `25`. |
| `cursor` | string | Cursor from nextCursor of the previous page. |

### Request

```bash
curl "https://api.lifebutler.io/v1/workspaces/f8Hn3wQz0a/documents" \
  -H "Authorization: Bearer $LIFEBUTLER_KEY"
```

### Response `200`

| Field | Type | Description |
|---|---|---|
| `data` | array of Document |  |
| `data[].id` | string |  |
| `data[].title` | string |  |
| `data[].category` | string | invoice, contract, insurance, bank, tax, payslip, medical, school, authority, warranty, receipt, letter, other |
| `data[].fileName` | string |  |
| `data[].mimeType` | string |  |
| `data[].size` | integer | Bytes. |
| `data[].documentDate` | string or null | YYYY-MM-DD: set by hand, else read by the AI. |
| `data[].notes` | string |  |
| `data[].sha256` | string or null |  |
| `data[].createdBy` | string or null |  |
| `data[].createdAt` | string or null |  |
| `data[].analysis` | DocumentAnalysis |  |
| `data[].analysis.status` | string | none, pending, done, error, refused, unsupported, tooLarge, off, noCredits or quotaExceeded. |
| `data[].analysis.summary` | string or null |  |
| `data[].analysis.issuer` | string or null |  |
| `data[].analysis.result` | object or null | Full AI result: payment (payee, amount, IBAN, due date), contract, deadlines, events, tasks, tags. |
| `nextCursor` | string or null | Pass as cursor to get the next page; null on the last page. |

```json
{
  "data": [
    {
      "id": "Ab3Cd5Ef7G",
      "title": "Elternabend 3b",
      "category": "string",
      "fileName": "rechnung.pdf",
      "mimeType": "application/pdf",
      "size": 184320,
      "documentDate": "2026-11-20",
      "notes": "",
      "sha256": "string",
      "createdBy": "string",
      "createdAt": "2026-11-20T19:30:00+01:00",
      "analysis": {
        "status": "string",
        "summary": "string",
        "issuer": "string",
        "result": {}
      }
    }
  ],
  "nextCursor": "string"
}
```

## Upload a document

**`POST https://api.lifebutler.io/v1/workspaces/{workspaceId}/documents`** · scope `documents:write` · MCP tool `upload_document`

Send the file as the raw request body with its Content-Type (PDF, JPEG, PNG, WebP, GIF, HEIC; max 25 MB) and the file name in the query. Like an upload in the app: a duplicate (same content) answers 409 with its id, the file counts towards the owner's storage, and – if the workspace has AI on and your document setting is automatic – it is analysed right away (1 credit per page).

### Path

| Field | Type | Description |
|---|---|---|
| `workspaceId` | string | Workspace id (from list_workspaces). |

### Query

| Field | Type | Description |
|---|---|---|
| `fileName` *(required)* | string | File name incl. extension, e.g. "rechnung.pdf". |
| `title` | string | Title (default: the file name without extension). |

### Body

The file's bytes; Content-Type: application/pdf, image/jpeg, image/png, image/webp, image/gif or image/heic.

### Request

```bash
curl -X POST "https://api.lifebutler.io/v1/workspaces/f8Hn3wQz0a/documents?fileName=rechnung.pdf" \
  -H "Authorization: Bearer $LIFEBUTLER_KEY" \
  -H "Content-Type: application/pdf" \
  --data-binary @rechnung.pdf
```

### Response `201`

| Field | Type | Description |
|---|---|---|
| `id` | string |  |
| `title` | string |  |
| `category` | string | invoice, contract, insurance, bank, tax, payslip, medical, school, authority, warranty, receipt, letter, other |
| `fileName` | string |  |
| `mimeType` | string |  |
| `size` | integer | Bytes. |
| `documentDate` | string or null | YYYY-MM-DD: set by hand, else read by the AI. |
| `notes` | string |  |
| `sha256` | string or null |  |
| `createdBy` | string or null |  |
| `createdAt` | string or null |  |
| `analysis` | DocumentAnalysis |  |
| `analysis.status` | string | none, pending, done, error, refused, unsupported, tooLarge, off, noCredits or quotaExceeded. |
| `analysis.summary` | string or null |  |
| `analysis.issuer` | string or null |  |
| `analysis.result` | object or null | Full AI result: payment (payee, amount, IBAN, due date), contract, deadlines, events, tasks, tags. |

```json
{
  "id": "Ab3Cd5Ef7G",
  "title": "Elternabend 3b",
  "category": "string",
  "fileName": "rechnung.pdf",
  "mimeType": "application/pdf",
  "size": 184320,
  "documentDate": "2026-11-20",
  "notes": "",
  "sha256": "string",
  "createdBy": "string",
  "createdAt": "2026-11-20T19:30:00+01:00",
  "analysis": {
    "status": "string",
    "summary": "string",
    "issuer": "string",
    "result": {}
  }
}
```

## Get a document

**`GET https://api.lifebutler.io/v1/workspaces/{workspaceId}/documents/{documentId}`** · scope `documents:read` · MCP tool `get_document`

Metadata and the AI analysis (summary, issuer, payment, deadlines, …). The file itself: download_document.

### Path

| Field | Type | Description |
|---|---|---|
| `workspaceId` | string | Workspace id (from list_workspaces). |
| `documentId` | string |  |

### Request

```bash
curl "https://api.lifebutler.io/v1/workspaces/f8Hn3wQz0a/documents/Dc5Yh1Pt8Q" \
  -H "Authorization: Bearer $LIFEBUTLER_KEY"
```

### Response `200`

| Field | Type | Description |
|---|---|---|
| `id` | string |  |
| `title` | string |  |
| `category` | string | invoice, contract, insurance, bank, tax, payslip, medical, school, authority, warranty, receipt, letter, other |
| `fileName` | string |  |
| `mimeType` | string |  |
| `size` | integer | Bytes. |
| `documentDate` | string or null | YYYY-MM-DD: set by hand, else read by the AI. |
| `notes` | string |  |
| `sha256` | string or null |  |
| `createdBy` | string or null |  |
| `createdAt` | string or null |  |
| `analysis` | DocumentAnalysis |  |
| `analysis.status` | string | none, pending, done, error, refused, unsupported, tooLarge, off, noCredits or quotaExceeded. |
| `analysis.summary` | string or null |  |
| `analysis.issuer` | string or null |  |
| `analysis.result` | object or null | Full AI result: payment (payee, amount, IBAN, due date), contract, deadlines, events, tasks, tags. |

```json
{
  "id": "Ab3Cd5Ef7G",
  "title": "Elternabend 3b",
  "category": "string",
  "fileName": "rechnung.pdf",
  "mimeType": "application/pdf",
  "size": 184320,
  "documentDate": "2026-11-20",
  "notes": "",
  "sha256": "string",
  "createdBy": "string",
  "createdAt": "2026-11-20T19:30:00+01:00",
  "analysis": {
    "status": "string",
    "summary": "string",
    "issuer": "string",
    "result": {}
  }
}
```

## Change a document

**`PATCH https://api.lifebutler.io/v1/workspaces/{workspaceId}/documents/{documentId}`** · scope `documents:write` · MCP tool `update_document`

Title, category, notes or date. What you set here is kept even if the AI analyses the document again.

### Path

| Field | Type | Description |
|---|---|---|
| `workspaceId` | string | Workspace id (from list_workspaces). |
| `documentId` | string |  |

### Body

| Field | Type | Description |
|---|---|---|
| `title` | string |  |
| `category` | `invoice` \| `contract` \| `insurance` \| `bank` \| `tax` \| `payslip` \| `medical` \| `school` \| `authority` \| `warranty` \| `receipt` \| `letter` \| `other` |  |
| `notes` | string |  |
| `documentDate` | string or null | YYYY-MM-DD; null goes back to the AI's date. |

### Request

```bash
curl -X PATCH "https://api.lifebutler.io/v1/workspaces/f8Hn3wQz0a/documents/Dc5Yh1Pt8Q" \
  -H "Authorization: Bearer $LIFEBUTLER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "Elternabend 3b"}'
```

### Response `200`

| Field | Type | Description |
|---|---|---|
| `id` | string |  |
| `title` | string |  |
| `category` | string | invoice, contract, insurance, bank, tax, payslip, medical, school, authority, warranty, receipt, letter, other |
| `fileName` | string |  |
| `mimeType` | string |  |
| `size` | integer | Bytes. |
| `documentDate` | string or null | YYYY-MM-DD: set by hand, else read by the AI. |
| `notes` | string |  |
| `sha256` | string or null |  |
| `createdBy` | string or null |  |
| `createdAt` | string or null |  |
| `analysis` | DocumentAnalysis |  |
| `analysis.status` | string | none, pending, done, error, refused, unsupported, tooLarge, off, noCredits or quotaExceeded. |
| `analysis.summary` | string or null |  |
| `analysis.issuer` | string or null |  |
| `analysis.result` | object or null | Full AI result: payment (payee, amount, IBAN, due date), contract, deadlines, events, tasks, tags. |

```json
{
  "id": "Ab3Cd5Ef7G",
  "title": "Elternabend 3b",
  "category": "string",
  "fileName": "rechnung.pdf",
  "mimeType": "application/pdf",
  "size": 184320,
  "documentDate": "2026-11-20",
  "notes": "",
  "sha256": "string",
  "createdBy": "string",
  "createdAt": "2026-11-20T19:30:00+01:00",
  "analysis": {
    "status": "string",
    "summary": "string",
    "issuer": "string",
    "result": {}
  }
}
```

## Delete a document

**`DELETE https://api.lifebutler.io/v1/workspaces/{workspaceId}/documents/{documentId}`** · scope `documents:write` · MCP tool `delete_document`

Deletes the document and its file for everyone.

### Path

| Field | Type | Description |
|---|---|---|
| `workspaceId` | string | Workspace id (from list_workspaces). |
| `documentId` | string |  |

### Request

```bash
curl -X DELETE "https://api.lifebutler.io/v1/workspaces/f8Hn3wQz0a/documents/Dc5Yh1Pt8Q" \
  -H "Authorization: Bearer $LIFEBUTLER_KEY"
```

### Response `200`

| Field | Type | Description |
|---|---|---|
| `id` | string |  |
| `deleted` | `true` |  |

```json
{
  "id": "Ab3Cd5Ef7G",
  "deleted": false
}
```

## Download the file

**`GET https://api.lifebutler.io/v1/workspaces/{workspaceId}/documents/{documentId}/file`** · scope `documents:read`

The original file (PDF or image) with its Content-Type and file name.

### Path

| Field | Type | Description |
|---|---|---|
| `workspaceId` | string | Workspace id (from list_workspaces). |
| `documentId` | string |  |

### Request

```bash
curl "https://api.lifebutler.io/v1/workspaces/f8Hn3wQz0a/documents/Dc5Yh1Pt8Q/file" \
  -H "Authorization: Bearer $LIFEBUTLER_KEY"
```

### Response `200`

The file itself, with `Content-Type` and `Content-Disposition` (file name).

## Analyse a document with AI

**`POST https://api.lifebutler.io/v1/workspaces/{workspaceId}/documents/{documentId}/analyze`** · scope `documents:write` · MCP tool `analyze_document`

Starts the AI analysis (1 credit per page, paid by the workspace owner). It runs in the background: poll get_document until analysis.status is no longer pending. Needs AI turned on for the workspace.

### Path

| Field | Type | Description |
|---|---|---|
| `workspaceId` | string | Workspace id (from list_workspaces). |
| `documentId` | string |  |

### Body

| Field | Type | Description |
|---|---|---|
| `again` | boolean | Analyse a document that was already analysed once more (costs credits again). Default: `false`. |

### Request

```bash
curl -X POST "https://api.lifebutler.io/v1/workspaces/f8Hn3wQz0a/documents/Dc5Yh1Pt8Q/analyze" \
  -H "Authorization: Bearer $LIFEBUTLER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"again": false}'
```

### Response `202`

| Field | Type | Description |
|---|---|---|
| `id` | string |  |
| `title` | string |  |
| `category` | string | invoice, contract, insurance, bank, tax, payslip, medical, school, authority, warranty, receipt, letter, other |
| `fileName` | string |  |
| `mimeType` | string |  |
| `size` | integer | Bytes. |
| `documentDate` | string or null | YYYY-MM-DD: set by hand, else read by the AI. |
| `notes` | string |  |
| `sha256` | string or null |  |
| `createdBy` | string or null |  |
| `createdAt` | string or null |  |
| `analysis` | DocumentAnalysis |  |
| `analysis.status` | string | none, pending, done, error, refused, unsupported, tooLarge, off, noCredits or quotaExceeded. |
| `analysis.summary` | string or null |  |
| `analysis.issuer` | string or null |  |
| `analysis.result` | object or null | Full AI result: payment (payee, amount, IBAN, due date), contract, deadlines, events, tasks, tags. |

```json
{
  "id": "Ab3Cd5Ef7G",
  "title": "Elternabend 3b",
  "category": "string",
  "fileName": "rechnung.pdf",
  "mimeType": "application/pdf",
  "size": 184320,
  "documentDate": "2026-11-20",
  "notes": "",
  "sha256": "string",
  "createdBy": "string",
  "createdAt": "2026-11-20T19:30:00+01:00",
  "analysis": {
    "status": "string",
    "summary": "string",
    "issuer": "string",
    "result": {}
  }
}
```
