# Tasks – API reference

> To-dos with exact or fuzzy due dates, assignees and repetition.

To-dos with exact or fuzzy due dates, assignees and repetition.

## List tasks

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

Open tasks by default, sorted by due date (tasks without a date last).

### Path

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

### Query

| Field | Type | Description |
|---|---|---|
| `status` | `open` \| `done` \| `all` |  Default: `"open"`. |
| `assigneeId` | string | Only tasks assigned to this member. |
| `limit` | integer |  Default: `200`. |

### Request

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

### Response `200`

| Field | Type | Description |
|---|---|---|
| `data` | array of Task |  |
| `data[].id` | string |  |
| `data[].title` | string |  |
| `data[].notes` | string |  |
| `data[].assigneeIds` | array of string |  |
| `data[].dueKind` | `none` \| `date` \| `month` \| `quarter` \| `year` \| `someday` | none, date (exact day), month, quarter, year or someday. |
| `data[].dueDate` | string or null | YYYY-MM-DD: the day, or the first day of the month/quarter/year. |
| `data[].time` | string or null | HH:MM (Berlin) with a push reminder; only for dueKind date. |
| `data[].recurrence` | TaskRecurrence or null |  |
| `data[].recurrence.frequency` | `daily` \| `weekly` \| `monthly` \| `yearly` |  |
| `data[].recurrence.interval` | integer | Default: `1`. |
| `data[].recurrence.afterCompletion` | boolean | Count the next due date from the day it was done (e.g. change the water filter 60 days after the last change). Default: `false`. |
| `data[].done` | boolean |  |
| `data[].doneAt` | string or null |  |
| `data[].doneBy` | string or null |  |
| `data[].createdBy` | string or null |  |
| `data[].createdAt` | string or null |  |
| `truncated` | boolean |  |

```json
{
  "data": [
    {
      "id": "Ab3Cd5Ef7G",
      "title": "Elternabend 3b",
      "notes": "",
      "assigneeIds": [
        "string"
      ],
      "dueKind": "none",
      "dueDate": "2026-11-20",
      "time": "18:00",
      "recurrence": {
        "frequency": "daily",
        "interval": 1,
        "afterCompletion": false
      },
      "done": false,
      "doneAt": "2026-11-20T19:30:00+01:00",
      "doneBy": "string",
      "createdBy": "string",
      "createdAt": "2026-11-20T19:30:00+01:00"
    }
  ],
  "truncated": false
}
```

## Create a task

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

A to-do with an optional exact or fuzzy due date (this month, this quarter, someday …), assignees and repetition.

### Path

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

### Body

| Field | Type | Description |
|---|---|---|
| `title` *(required)* | string |  |
| `notes` | string |  |
| `assigneeIds` | array of string | Member ids (list_members). |
| `dueKind` | `none` \| `date` \| `month` \| `quarter` \| `year` \| `someday` | Default: date when dueDate is given, else none. |
| `dueDate` | string or null | YYYY-MM-DD; for month/quarter/year any day inside the period. |
| `time` | string or null | HH:MM (Berlin), only with dueKind date: push reminder at that time. |
| `recurrence` | TaskRecurrence or null | Needs a due date. |
| `recurrence.frequency` *(required)* | `daily` \| `weekly` \| `monthly` \| `yearly` |  |
| `recurrence.interval` *(required)* | integer | Default: `1`. |
| `recurrence.afterCompletion` *(required)* | boolean | Count the next due date from the day it was done (e.g. change the water filter 60 days after the last change). Default: `false`. |

### Request

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

### Response `201`

| Field | Type | Description |
|---|---|---|
| `id` | string |  |
| `title` | string |  |
| `notes` | string |  |
| `assigneeIds` | array of string |  |
| `dueKind` | `none` \| `date` \| `month` \| `quarter` \| `year` \| `someday` | none, date (exact day), month, quarter, year or someday. |
| `dueDate` | string or null | YYYY-MM-DD: the day, or the first day of the month/quarter/year. |
| `time` | string or null | HH:MM (Berlin) with a push reminder; only for dueKind date. |
| `recurrence` | TaskRecurrence or null |  |
| `recurrence.frequency` | `daily` \| `weekly` \| `monthly` \| `yearly` |  |
| `recurrence.interval` | integer | Default: `1`. |
| `recurrence.afterCompletion` | boolean | Count the next due date from the day it was done (e.g. change the water filter 60 days after the last change). Default: `false`. |
| `done` | boolean |  |
| `doneAt` | string or null |  |
| `doneBy` | string or null |  |
| `createdBy` | string or null |  |
| `createdAt` | string or null |  |

```json
{
  "id": "Ab3Cd5Ef7G",
  "title": "Elternabend 3b",
  "notes": "",
  "assigneeIds": [
    "string"
  ],
  "dueKind": "none",
  "dueDate": "2026-11-20",
  "time": "18:00",
  "recurrence": {
    "frequency": "daily",
    "interval": 1,
    "afterCompletion": false
  },
  "done": false,
  "doneAt": "2026-11-20T19:30:00+01:00",
  "doneBy": "string",
  "createdBy": "string",
  "createdAt": "2026-11-20T19:30:00+01:00"
}
```

## Get a task

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

One task.

### Path

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

### Request

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

### Response `200`

| Field | Type | Description |
|---|---|---|
| `id` | string |  |
| `title` | string |  |
| `notes` | string |  |
| `assigneeIds` | array of string |  |
| `dueKind` | `none` \| `date` \| `month` \| `quarter` \| `year` \| `someday` | none, date (exact day), month, quarter, year or someday. |
| `dueDate` | string or null | YYYY-MM-DD: the day, or the first day of the month/quarter/year. |
| `time` | string or null | HH:MM (Berlin) with a push reminder; only for dueKind date. |
| `recurrence` | TaskRecurrence or null |  |
| `recurrence.frequency` | `daily` \| `weekly` \| `monthly` \| `yearly` |  |
| `recurrence.interval` | integer | Default: `1`. |
| `recurrence.afterCompletion` | boolean | Count the next due date from the day it was done (e.g. change the water filter 60 days after the last change). Default: `false`. |
| `done` | boolean |  |
| `doneAt` | string or null |  |
| `doneBy` | string or null |  |
| `createdBy` | string or null |  |
| `createdAt` | string or null |  |

```json
{
  "id": "Ab3Cd5Ef7G",
  "title": "Elternabend 3b",
  "notes": "",
  "assigneeIds": [
    "string"
  ],
  "dueKind": "none",
  "dueDate": "2026-11-20",
  "time": "18:00",
  "recurrence": {
    "frequency": "daily",
    "interval": 1,
    "afterCompletion": false
  },
  "done": false,
  "doneAt": "2026-11-20T19:30:00+01:00",
  "doneBy": "string",
  "createdBy": "string",
  "createdAt": "2026-11-20T19:30:00+01:00"
}
```

## Change a task

**`PATCH https://api.lifebutler.io/v1/workspaces/{workspaceId}/tasks/{taskId}`** · scope `tasks:write` · MCP tool `update_task`

Changes only the fields you send. Send dueKind none to remove the due date, recurrence null to stop repeating.

### Path

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

### Body

| Field | Type | Description |
|---|---|---|
| `title` | string |  |
| `notes` | string |  |
| `assigneeIds` | array of string | Member ids (list_members). |
| `dueKind` | `none` \| `date` \| `month` \| `quarter` \| `year` \| `someday` | Default: date when dueDate is given, else none. |
| `dueDate` | string or null | YYYY-MM-DD; for month/quarter/year any day inside the period. |
| `time` | string or null | HH:MM (Berlin), only with dueKind date: push reminder at that time. |
| `recurrence` | TaskRecurrence or null | Needs a due date. |
| `recurrence.frequency` *(required)* | `daily` \| `weekly` \| `monthly` \| `yearly` |  |
| `recurrence.interval` *(required)* | integer | Default: `1`. |
| `recurrence.afterCompletion` *(required)* | boolean | Count the next due date from the day it was done (e.g. change the water filter 60 days after the last change). Default: `false`. |

### Request

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

### Response `200`

| Field | Type | Description |
|---|---|---|
| `id` | string |  |
| `title` | string |  |
| `notes` | string |  |
| `assigneeIds` | array of string |  |
| `dueKind` | `none` \| `date` \| `month` \| `quarter` \| `year` \| `someday` | none, date (exact day), month, quarter, year or someday. |
| `dueDate` | string or null | YYYY-MM-DD: the day, or the first day of the month/quarter/year. |
| `time` | string or null | HH:MM (Berlin) with a push reminder; only for dueKind date. |
| `recurrence` | TaskRecurrence or null |  |
| `recurrence.frequency` | `daily` \| `weekly` \| `monthly` \| `yearly` |  |
| `recurrence.interval` | integer | Default: `1`. |
| `recurrence.afterCompletion` | boolean | Count the next due date from the day it was done (e.g. change the water filter 60 days after the last change). Default: `false`. |
| `done` | boolean |  |
| `doneAt` | string or null |  |
| `doneBy` | string or null |  |
| `createdBy` | string or null |  |
| `createdAt` | string or null |  |

```json
{
  "id": "Ab3Cd5Ef7G",
  "title": "Elternabend 3b",
  "notes": "",
  "assigneeIds": [
    "string"
  ],
  "dueKind": "none",
  "dueDate": "2026-11-20",
  "time": "18:00",
  "recurrence": {
    "frequency": "daily",
    "interval": 1,
    "afterCompletion": false
  },
  "done": false,
  "doneAt": "2026-11-20T19:30:00+01:00",
  "doneBy": "string",
  "createdBy": "string",
  "createdAt": "2026-11-20T19:30:00+01:00"
}
```

## Delete a task

**`DELETE https://api.lifebutler.io/v1/workspaces/{workspaceId}/tasks/{taskId}`** · scope `tasks:write` · MCP tool `delete_task`

Deletes the task for everyone.

### Path

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

### Request

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

### Response `200`

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

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

## Complete a task

**`POST https://api.lifebutler.io/v1/workspaces/{workspaceId}/tasks/{taskId}/complete`** · scope `tasks:write` · MCP tool `complete_task`

Ticks a task off, like in the app. A repeating task moves to its next due date and stays open (missed dates are skipped); when its series has ended it is done.

### Path

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

### Request

```bash
curl -X POST "https://api.lifebutler.io/v1/workspaces/f8Hn3wQz0a/tasks/Tk4Rm8Zs1C/complete" \
  -H "Authorization: Bearer $LIFEBUTLER_KEY"
```

### Response `200`

| Field | Type | Description |
|---|---|---|
| `id` | string |  |
| `title` | string |  |
| `notes` | string |  |
| `assigneeIds` | array of string |  |
| `dueKind` | `none` \| `date` \| `month` \| `quarter` \| `year` \| `someday` | none, date (exact day), month, quarter, year or someday. |
| `dueDate` | string or null | YYYY-MM-DD: the day, or the first day of the month/quarter/year. |
| `time` | string or null | HH:MM (Berlin) with a push reminder; only for dueKind date. |
| `recurrence` | TaskRecurrence or null |  |
| `recurrence.frequency` | `daily` \| `weekly` \| `monthly` \| `yearly` |  |
| `recurrence.interval` | integer | Default: `1`. |
| `recurrence.afterCompletion` | boolean | Count the next due date from the day it was done (e.g. change the water filter 60 days after the last change). Default: `false`. |
| `done` | boolean |  |
| `doneAt` | string or null |  |
| `doneBy` | string or null |  |
| `createdBy` | string or null |  |
| `createdAt` | string or null |  |

```json
{
  "id": "Ab3Cd5Ef7G",
  "title": "Elternabend 3b",
  "notes": "",
  "assigneeIds": [
    "string"
  ],
  "dueKind": "none",
  "dueDate": "2026-11-20",
  "time": "18:00",
  "recurrence": {
    "frequency": "daily",
    "interval": 1,
    "afterCompletion": false
  },
  "done": false,
  "doneAt": "2026-11-20T19:30:00+01:00",
  "doneBy": "string",
  "createdBy": "string",
  "createdAt": "2026-11-20T19:30:00+01:00"
}
```

## Reopen a task

**`POST https://api.lifebutler.io/v1/workspaces/{workspaceId}/tasks/{taskId}/reopen`** · scope `tasks:write` · MCP tool `reopen_task`

Marks a done task as open again.

### Path

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

### Request

```bash
curl -X POST "https://api.lifebutler.io/v1/workspaces/f8Hn3wQz0a/tasks/Tk4Rm8Zs1C/reopen" \
  -H "Authorization: Bearer $LIFEBUTLER_KEY"
```

### Response `200`

| Field | Type | Description |
|---|---|---|
| `id` | string |  |
| `title` | string |  |
| `notes` | string |  |
| `assigneeIds` | array of string |  |
| `dueKind` | `none` \| `date` \| `month` \| `quarter` \| `year` \| `someday` | none, date (exact day), month, quarter, year or someday. |
| `dueDate` | string or null | YYYY-MM-DD: the day, or the first day of the month/quarter/year. |
| `time` | string or null | HH:MM (Berlin) with a push reminder; only for dueKind date. |
| `recurrence` | TaskRecurrence or null |  |
| `recurrence.frequency` | `daily` \| `weekly` \| `monthly` \| `yearly` |  |
| `recurrence.interval` | integer | Default: `1`. |
| `recurrence.afterCompletion` | boolean | Count the next due date from the day it was done (e.g. change the water filter 60 days after the last change). Default: `false`. |
| `done` | boolean |  |
| `doneAt` | string or null |  |
| `doneBy` | string or null |  |
| `createdBy` | string or null |  |
| `createdAt` | string or null |  |

```json
{
  "id": "Ab3Cd5Ef7G",
  "title": "Elternabend 3b",
  "notes": "",
  "assigneeIds": [
    "string"
  ],
  "dueKind": "none",
  "dueDate": "2026-11-20",
  "time": "18:00",
  "recurrence": {
    "frequency": "daily",
    "interval": 1,
    "afterCompletion": false
  },
  "done": false,
  "doneAt": "2026-11-20T19:30:00+01:00",
  "doneBy": "string",
  "createdBy": "string",
  "createdAt": "2026-11-20T19:30:00+01:00"
}
```
