{
  "openapi": "3.1.0",
  "info": {
    "title": "LifeButler API",
    "version": "1.0.0",
    "description": "Read and change your LifeButler workspaces from your own code: calendar, tasks, lists, documents, smart search and the butler. Available with LifeButler Pro and Premium. Docs: https://lifebutler.io/developers",
    "contact": {
      "name": "LifeButler",
      "url": "https://lifebutler.io/developers",
      "email": "support@lifebutler.io"
    }
  },
  "servers": [
    {
      "url": "https://api.lifebutler.io/v1"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Workspaces",
      "description": "The workspaces a key may use, and their members."
    },
    {
      "name": "Calendar",
      "description": "Appointments, including repeating ones."
    },
    {
      "name": "Tasks",
      "description": "To-dos with exact or fuzzy due dates, assignees and repetition."
    },
    {
      "name": "Lists",
      "description": "Shopping and to-do lists and their items."
    },
    {
      "name": "Documents",
      "description": "Stored files with their AI analysis: search, upload, download."
    },
    {
      "name": "Search & Butler",
      "description": "Smart search by meaning and the AI butler."
    }
  ],
  "paths": {
    "/me": {
      "get": {
        "operationId": "getMe",
        "summary": "Who am I",
        "description": "The account behind the key, its plan, and the key's scopes. A cheap way to test a key.\n\nScope: `workspaces:read` · MCP tool: `get_me`",
        "tags": [
          "Workspaces"
        ],
        "x-scope": "workspaces:read",
        "x-mcp-tool": "get_me",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "userId": {
                      "type": "string"
                    },
                    "plan": {
                      "type": "string",
                      "description": "pro or premium."
                    },
                    "key": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "scopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "expiresAt": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "id",
                        "scopes",
                        "expiresAt"
                      ],
                      "additionalProperties": false
                    },
                    "sharedWorkspaceLimit": {
                      "type": "number",
                      "description": "Shared workspaces your plan allows for the API (the personal one is always included)."
                    }
                  },
                  "required": [
                    "userId",
                    "plan",
                    "key",
                    "sharedWorkspaceLimit"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces": {
      "get": {
        "operationId": "listWorkspaces",
        "summary": "List workspaces",
        "description": "The workspaces this key was granted, each with a status. Only workspaces where you are owner or admin can be used; the ids are what every other call takes as workspaceId.\n\nScope: `workspaces:read` · MCP tool: `list_workspaces`",
        "tags": [
          "Workspaces"
        ],
        "x-scope": "workspaces:read",
        "x-mcp-tool": "list_workspaces",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Workspace"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}": {
      "get": {
        "operationId": "getWorkspace",
        "summary": "Get a workspace",
        "description": "Name, type and whether AI features are on.\n\nScope: `workspaces:read` · MCP tool: `get_workspace`",
        "tags": [
          "Workspaces"
        ],
        "x-scope": "workspaces:read",
        "x-mcp-tool": "get_workspace",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Workspace"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/members": {
      "get": {
        "operationId": "listMembers",
        "summary": "List members",
        "description": "Everyone in the workspace, including members without an account. Use the ids to assign tasks and invite to appointments.\n\nScope: `workspaces:read` · MCP tool: `list_members`",
        "tags": [
          "Workspaces"
        ],
        "x-scope": "workspaces:read",
        "x-mcp-tool": "list_members",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Member"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/events": {
      "get": {
        "operationId": "listEvents",
        "summary": "List appointments in a time range",
        "description": "Every appointment that overlaps [from, to], with repeating series expanded into single occurrences, sorted by start. Default range: today and the next 30 days; at most 366 days and 1000 occurrences.\n\nScope: `calendar:read` · MCP tool: `list_events`",
        "tags": [
          "Calendar"
        ],
        "x-scope": "calendar:read",
        "x-mcp-tool": "list_events",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "ISO 8601 or YYYY-MM-DD (default: start of today, Berlin).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "ISO 8601 or YYYY-MM-DD; a plain date includes that whole day (default: from + 30 days).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Occurrence"
                      }
                    },
                    "truncated": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "data",
                    "truncated"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createEvent",
        "summary": "Create an appointment",
        "description": "Creates an appointment, optionally repeating. Attendees get the usual push notification; linked Google calendars sync it like one made in the app.\n\nScope: `calendar:write` · MCP tool: `create_event`",
        "tags": [
          "Calendar"
        ],
        "x-scope": "calendar:write",
        "x-mcp-tool": "create_event",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "allDay": {
                    "description": "Default false.",
                    "type": "boolean"
                  },
                  "start": {
                    "type": "string",
                    "description": "Timed: ISO 8601 (\"2026-11-20T19:30:00+01:00\"; without offset = Berlin time). All-day: \"YYYY-MM-DD\"."
                  },
                  "end": {
                    "description": "Timed: ISO 8601, after start (default start + 1 h). All-day: last day YYYY-MM-DD, inclusive (default: the start day).",
                    "type": "string"
                  },
                  "location": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 5000
                  },
                  "attendeeIds": {
                    "description": "Member ids (list_members).",
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "recurrence": {
                    "anyOf": [
                      {
                        "$ref": "#/components/schemas/Recurrence"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "title",
                  "start"
                ]
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/events/{eventId}": {
      "get": {
        "operationId": "getEvent",
        "summary": "Get an appointment",
        "description": "One appointment; for a series the series itself with its recurrence.\n\nScope: `calendar:read` · MCP tool: `get_event`",
        "tags": [
          "Calendar"
        ],
        "x-scope": "calendar:read",
        "x-mcp-tool": "get_event",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "eventId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateEvent",
        "summary": "Change an appointment",
        "description": "Changes only the fields you send. For a series this changes the whole series. Send recurrence: null to stop repeating. Read-only copies (source shared) answer 409.\n\nScope: `calendar:write` · MCP tool: `update_event`",
        "tags": [
          "Calendar"
        ],
        "x-scope": "calendar:write",
        "x-mcp-tool": "update_event",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "eventId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "allDay": {
                    "description": "Default false.",
                    "type": "boolean"
                  },
                  "start": {
                    "type": "string",
                    "description": "Timed: ISO 8601 (\"2026-11-20T19:30:00+01:00\"; without offset = Berlin time). All-day: \"YYYY-MM-DD\"."
                  },
                  "end": {
                    "description": "Timed: ISO 8601, after start (default start + 1 h). All-day: last day YYYY-MM-DD, inclusive (default: the start day).",
                    "type": "string"
                  },
                  "location": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 5000
                  },
                  "attendeeIds": {
                    "description": "Member ids (list_members).",
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "recurrence": {
                    "anyOf": [
                      {
                        "$ref": "#/components/schemas/Recurrence"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteEvent",
        "summary": "Delete an appointment",
        "description": "Deletes the appointment (for a series: all of it). Read-only copies answer 409.\n\nScope: `calendar:write` · MCP tool: `delete_event`",
        "tags": [
          "Calendar"
        ],
        "x-scope": "calendar:write",
        "x-mcp-tool": "delete_event",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "eventId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/tasks": {
      "get": {
        "operationId": "listTasks",
        "summary": "List tasks",
        "description": "Open tasks by default, sorted by due date (tasks without a date last).\n\nScope: `tasks:read` · MCP tool: `list_tasks`",
        "tags": [
          "Tasks"
        ],
        "x-scope": "tasks:read",
        "x-mcp-tool": "list_tasks",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "default": "open",
              "type": "string",
              "enum": [
                "open",
                "done",
                "all"
              ]
            }
          },
          {
            "name": "assigneeId",
            "in": "query",
            "required": false,
            "description": "Only tasks assigned to this member.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 200,
              "type": "integer",
              "minimum": 1,
              "maximum": 500
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Task"
                      }
                    },
                    "truncated": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "data",
                    "truncated"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createTask",
        "summary": "Create a task",
        "description": "A to-do with an optional exact or fuzzy due date (this month, this quarter, someday …), assignees and repetition.\n\nScope: `tasks:write` · MCP tool: `create_task`",
        "tags": [
          "Tasks"
        ],
        "x-scope": "tasks:write",
        "x-mcp-tool": "create_task",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 5000
                  },
                  "assigneeIds": {
                    "description": "Member ids (list_members).",
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "dueKind": {
                    "description": "Default: date when dueDate is given, else none.",
                    "type": "string",
                    "enum": [
                      "none",
                      "date",
                      "month",
                      "quarter",
                      "year",
                      "someday"
                    ]
                  },
                  "dueDate": {
                    "description": "YYYY-MM-DD; for month/quarter/year any day inside the period.",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "time": {
                    "description": "HH:MM (Berlin), only with dueKind date: push reminder at that time.",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "recurrence": {
                    "description": "Needs a due date.",
                    "anyOf": [
                      {
                        "$ref": "#/components/schemas/TaskRecurrence"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "title"
                ]
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/tasks/{taskId}": {
      "get": {
        "operationId": "getTask",
        "summary": "Get a task",
        "description": "One task.\n\nScope: `tasks:read` · MCP tool: `get_task`",
        "tags": [
          "Tasks"
        ],
        "x-scope": "tasks:read",
        "x-mcp-tool": "get_task",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateTask",
        "summary": "Change a task",
        "description": "Changes only the fields you send. Send dueKind none to remove the due date, recurrence null to stop repeating.\n\nScope: `tasks:write` · MCP tool: `update_task`",
        "tags": [
          "Tasks"
        ],
        "x-scope": "tasks:write",
        "x-mcp-tool": "update_task",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 5000
                  },
                  "assigneeIds": {
                    "description": "Member ids (list_members).",
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "dueKind": {
                    "description": "Default: date when dueDate is given, else none.",
                    "type": "string",
                    "enum": [
                      "none",
                      "date",
                      "month",
                      "quarter",
                      "year",
                      "someday"
                    ]
                  },
                  "dueDate": {
                    "description": "YYYY-MM-DD; for month/quarter/year any day inside the period.",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "time": {
                    "description": "HH:MM (Berlin), only with dueKind date: push reminder at that time.",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "recurrence": {
                    "description": "Needs a due date.",
                    "anyOf": [
                      {
                        "$ref": "#/components/schemas/TaskRecurrence"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteTask",
        "summary": "Delete a task",
        "description": "Deletes the task for everyone.\n\nScope: `tasks:write` · MCP tool: `delete_task`",
        "tags": [
          "Tasks"
        ],
        "x-scope": "tasks:write",
        "x-mcp-tool": "delete_task",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/tasks/{taskId}/complete": {
      "post": {
        "operationId": "completeTask",
        "summary": "Complete a task",
        "description": "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.\n\nScope: `tasks:write` · MCP tool: `complete_task`",
        "tags": [
          "Tasks"
        ],
        "x-scope": "tasks:write",
        "x-mcp-tool": "complete_task",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/tasks/{taskId}/reopen": {
      "post": {
        "operationId": "reopenTask",
        "summary": "Reopen a task",
        "description": "Marks a done task as open again.\n\nScope: `tasks:write` · MCP tool: `reopen_task`",
        "tags": [
          "Tasks"
        ],
        "x-scope": "tasks:write",
        "x-mcp-tool": "reopen_task",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/lists": {
      "get": {
        "operationId": "listLists",
        "summary": "List lists",
        "description": "All shopping and to-do lists of the workspace, oldest first (like in the app).\n\nScope: `lists:read` · MCP tool: `list_lists`",
        "tags": [
          "Lists"
        ],
        "x-scope": "lists:read",
        "x-mcp-tool": "list_lists",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/List"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createList",
        "summary": "Create a list",
        "description": "A new, empty list.\n\nScope: `lists:write` · MCP tool: `create_list`",
        "tags": [
          "Lists"
        ],
        "x-scope": "lists:write",
        "x-mcp-tool": "create_list",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/List"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "type": {
                    "default": "shopping",
                    "type": "string",
                    "enum": [
                      "shopping",
                      "todo"
                    ]
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/lists/{listId}": {
      "patch": {
        "operationId": "updateList",
        "summary": "Rename a list",
        "description": "Changes the list's name.\n\nScope: `lists:write` · MCP tool: `update_list`",
        "tags": [
          "Lists"
        ],
        "x-scope": "lists:write",
        "x-mcp-tool": "update_list",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "listId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/List"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteList",
        "summary": "Delete a list",
        "description": "Deletes the list with all its items.\n\nScope: `lists:write` · MCP tool: `delete_list`",
        "tags": [
          "Lists"
        ],
        "x-scope": "lists:write",
        "x-mcp-tool": "delete_list",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "listId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/lists/{listId}/items": {
      "get": {
        "operationId": "listItems",
        "summary": "List items",
        "description": "The items of a list, newest first. Ticked-off items only with includeChecked.\n\nScope: `lists:read` · MCP tool: `list_items`",
        "tags": [
          "Lists"
        ],
        "x-scope": "lists:read",
        "x-mcp-tool": "list_items",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "listId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "includeChecked",
            "in": "query",
            "required": false,
            "description": "Also return ticked-off items.",
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "list": {
                      "$ref": "#/components/schemas/List"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ListItem"
                      }
                    }
                  },
                  "required": [
                    "list",
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "addItems",
        "summary": "Add items",
        "description": "Adds one or more items, e.g. [\"Milch\", \"Eier (10)\"].\n\nScope: `lists:write` · MCP tool: `add_items`",
        "tags": [
          "Lists"
        ],
        "x-scope": "lists:write",
        "x-mcp-tool": "add_items",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "listId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ListItem"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "items": {
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200
                    }
                  }
                },
                "required": [
                  "items"
                ]
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/lists/{listId}/items/{itemId}": {
      "patch": {
        "operationId": "updateItem",
        "summary": "Change or tick off an item",
        "description": "Send checked: true to tick an item off (false to untick), text to rename it.\n\nScope: `lists:write` · MCP tool: `update_item`",
        "tags": [
          "Lists"
        ],
        "x-scope": "lists:write",
        "x-mcp-tool": "update_item",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "listId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListItem"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "checked": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteItem",
        "summary": "Remove an item",
        "description": "Removes the item from the list.\n\nScope: `lists:write` · MCP tool: `delete_item`",
        "tags": [
          "Lists"
        ],
        "x-scope": "lists:write",
        "x-mcp-tool": "delete_item",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "listId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/documents": {
      "get": {
        "operationId": "listDocuments",
        "summary": "List and search documents",
        "description": "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.\n\nScope: `documents:read` · MCP tool: `list_documents`",
        "tags": [
          "Documents"
        ],
        "x-scope": "documents:read",
        "x-mcp-tool": "list_documents",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Words to find, e.g. \"stadtwerke 2026\".",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "invoice",
                "contract",
                "insurance",
                "bank",
                "tax",
                "payslip",
                "medical",
                "school",
                "authority",
                "warranty",
                "receipt",
                "letter",
                "other"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of results (1–100, default 25).",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor from nextCursor of the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Document"
                      }
                    },
                    "nextCursor": {
                      "description": "Pass as cursor to get the next page; null on the last page.",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "nextCursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "uploadDocument",
        "summary": "Upload a document",
        "description": "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).\n\nScope: `documents:write` · MCP tool: `upload_document`",
        "tags": [
          "Documents"
        ],
        "x-scope": "documents:write",
        "x-mcp-tool": "upload_document",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fileName",
            "in": "query",
            "required": true,
            "description": "File name incl. extension, e.g. \"rechnung.pdf\".",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "title",
            "in": "query",
            "required": false,
            "description": "Title (default: the file name without extension).",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Document"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "description": "The file's bytes; Content-Type: application/pdf, image/jpeg, image/png, image/webp, image/gif or image/heic.",
          "content": {
            "application/pdf": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/jpeg": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/png": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/webp": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/gif": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/heic": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/documents/{documentId}": {
      "get": {
        "operationId": "getDocument",
        "summary": "Get a document",
        "description": "Metadata and the AI analysis (summary, issuer, payment, deadlines, …). The file itself: download_document.\n\nScope: `documents:read` · MCP tool: `get_document`",
        "tags": [
          "Documents"
        ],
        "x-scope": "documents:read",
        "x-mcp-tool": "get_document",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "documentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Document"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateDocument",
        "summary": "Change a document",
        "description": "Title, category, notes or date. What you set here is kept even if the AI analyses the document again.\n\nScope: `documents:write` · MCP tool: `update_document`",
        "tags": [
          "Documents"
        ],
        "x-scope": "documents:write",
        "x-mcp-tool": "update_document",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "documentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Document"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "category": {
                    "type": "string",
                    "enum": [
                      "invoice",
                      "contract",
                      "insurance",
                      "bank",
                      "tax",
                      "payslip",
                      "medical",
                      "school",
                      "authority",
                      "warranty",
                      "receipt",
                      "letter",
                      "other"
                    ]
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 5000
                  },
                  "documentDate": {
                    "description": "YYYY-MM-DD; null goes back to the AI's date.",
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteDocument",
        "summary": "Delete a document",
        "description": "Deletes the document and its file for everyone.\n\nScope: `documents:write` · MCP tool: `delete_document`",
        "tags": [
          "Documents"
        ],
        "x-scope": "documents:write",
        "x-mcp-tool": "delete_document",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "documentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/documents/{documentId}/file": {
      "get": {
        "operationId": "downloadDocument",
        "summary": "Download the file",
        "description": "The original file (PDF or image) with its Content-Type and file name.\n\nScope: `documents:read`",
        "tags": [
          "Documents"
        ],
        "x-scope": "documents:read",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "documentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The file.",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/documents/{documentId}/analyze": {
      "post": {
        "operationId": "analyzeDocument",
        "summary": "Analyse a document with AI",
        "description": "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.\n\nScope: `documents:write` · MCP tool: `analyze_document`",
        "tags": [
          "Documents"
        ],
        "x-scope": "documents:write",
        "x-mcp-tool": "analyze_document",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "documentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Document"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "again": {
                    "default": false,
                    "description": "Analyse a document that was already analysed once more (costs credits again).",
                    "type": "boolean"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/search": {
      "get": {
        "operationId": "search",
        "summary": "Smart search",
        "description": "Search by meaning across the whole workspace – appointments, tasks, list items, notes, documents incl. their content, contracts, … (\"when is the car inspection due?\", \"Kita Rechnung\"). Needs AI turned on for the workspace; free of credits.\n\nScope: `search` · MCP tool: `search`",
        "tags": [
          "Search & Butler"
        ],
        "x-scope": "search",
        "x-mcp-tool": "search",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 10,
              "type": "integer",
              "minimum": 1,
              "maximum": 30
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SearchHit"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/workspaces/{workspaceId}/butler": {
      "post": {
        "operationId": "askButler",
        "summary": "Ask the butler",
        "description": "Ask in German or English about anything in the workspace (appointments, tasks, lists, documents, contracts, …) or tell it what to do (\"Put pasta and eggs on the shopping list and remind me on Friday to call the dentist\"). Returns the answer and proposed actions; with apply: true, lists items, tasks, appointments and notes are created right away (bills and meals stay proposals). Uses the workspace owner's credits like in the app (usually 1–2). Needs AI turned on for the workspace.\n\nScope: `butler` · MCP tool: `ask_butler`",
        "tags": [
          "Search & Butler"
        ],
        "x-scope": "butler",
        "x-mcp-tool": "ask_butler",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "description": "Workspace id (from list_workspaces).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "answer": {
                      "type": "string"
                    },
                    "actions": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ButlerAction"
                      }
                    },
                    "applied": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "How many actions were carried out (apply: true)."
                    },
                    "credits": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "Credits this answer cost."
                    }
                  },
                  "required": [
                    "answer",
                    "actions",
                    "applied",
                    "credits"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (see error.message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Plan without API access, missing scope, not an owner/admin, or over the plan's workspace limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found – also for workspaces outside this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit (120 requests per minute and key); see Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "question": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000
                  },
                  "history": {
                    "description": "Earlier turns of this conversation, oldest first.",
                    "maxItems": 8,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "role": {
                          "type": "string",
                          "enum": [
                            "user",
                            "assistant"
                          ]
                        },
                        "text": {
                          "type": "string",
                          "maxLength": 4000
                        }
                      },
                      "required": [
                        "role",
                        "text"
                      ]
                    }
                  },
                  "apply": {
                    "default": false,
                    "description": "Create the proposed items right away.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "question"
                ]
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Workspace": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "description": "Empty for the personal workspace."
          },
          "type": {
            "type": "string",
            "description": "personal, family, flat, friends, club, trip or company."
          },
          "personal": {
            "type": "boolean"
          },
          "role": {
            "description": "Your role: owner or admin (null when not accessible).",
            "type": [
              "string",
              "null"
            ]
          },
          "aiEnabled": {
            "type": "boolean",
            "description": "AI features (document analysis, smart search, butler) are turned on by the workspace admins."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "admin_required",
              "workspace_limit",
              "not_found"
            ],
            "description": "active, or why this key can't use the workspace right now."
          }
        },
        "required": [
          "id",
          "name",
          "type",
          "personal",
          "role",
          "aiEnabled",
          "status"
        ],
        "additionalProperties": false,
        "description": "A workspace (personal space or shared group) this key may use."
      },
      "Member": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Use in attendeeIds / assigneeIds."
          },
          "name": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "description": "owner, admin, adult, child or guest."
          },
          "hasAccount": {
            "type": "boolean",
            "description": "false for members without an account (kids, pets, grandparents)."
          }
        },
        "required": [
          "id",
          "name",
          "role",
          "hasAccount"
        ],
        "additionalProperties": false
      },
      "Occurrence": {
        "type": "object",
        "properties": {
          "eventId": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "allDay": {
            "type": "boolean"
          },
          "start": {
            "type": "string"
          },
          "end": {
            "type": "string"
          },
          "location": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "attendeeIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "recurring": {
            "type": "boolean"
          },
          "readOnly": {
            "type": "boolean"
          }
        },
        "required": [
          "eventId",
          "title",
          "allDay",
          "start",
          "end",
          "location",
          "notes",
          "attendeeIds",
          "recurring",
          "readOnly"
        ],
        "additionalProperties": false,
        "description": "One concrete appointment on the calendar; a series yields one per date."
      },
      "Event": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "allDay": {
            "type": "boolean"
          },
          "start": {
            "type": "string",
            "description": "ISO 8601, Europe/Berlin offset. First occurrence for series."
          },
          "end": {
            "type": "string"
          },
          "startDate": {
            "type": "string",
            "description": "YYYY-MM-DD (Berlin) of start."
          },
          "endDate": {
            "type": "string",
            "description": "YYYY-MM-DD (Berlin) of end, inclusive."
          },
          "location": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "attendeeIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Member ids."
          },
          "recurrence": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Recurrence"
              },
              {
                "type": "null"
              }
            ]
          },
          "source": {
            "type": "string",
            "enum": [
              "lifebutler",
              "google",
              "shared"
            ],
            "description": "google: comes from a member's linked Google calendar; shared: a read-only copy shared from another workspace."
          },
          "readOnly": {
            "type": "boolean"
          },
          "createdBy": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "allDay",
          "start",
          "end",
          "startDate",
          "endDate",
          "location",
          "notes",
          "attendeeIds",
          "recurrence",
          "source",
          "readOnly",
          "createdBy",
          "createdAt"
        ],
        "additionalProperties": false,
        "description": "An appointment (for series: the series itself)."
      },
      "Recurrence": {
        "type": "object",
        "properties": {
          "frequency": {
            "type": "string",
            "enum": [
              "daily",
              "weekly",
              "monthly",
              "yearly"
            ]
          },
          "interval": {
            "default": 1,
            "description": "Every n days/weeks/months/years.",
            "type": "integer",
            "minimum": 1,
            "maximum": 1000
          },
          "until": {
            "description": "Last day (YYYY-MM-DD) an occurrence may start on; null or missing: forever.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "frequency"
        ],
        "description": "Repeats from the first start; monthly on the 31st clamps to the month's last day."
      },
      "Task": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "assigneeIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "dueKind": {
            "type": "string",
            "enum": [
              "none",
              "date",
              "month",
              "quarter",
              "year",
              "someday"
            ],
            "description": "none, date (exact day), month, quarter, year or someday."
          },
          "dueDate": {
            "description": "YYYY-MM-DD: the day, or the first day of the month/quarter/year.",
            "type": [
              "string",
              "null"
            ]
          },
          "time": {
            "description": "HH:MM (Berlin) with a push reminder; only for dueKind date.",
            "type": [
              "string",
              "null"
            ]
          },
          "recurrence": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TaskRecurrence"
              },
              {
                "type": "null"
              }
            ]
          },
          "done": {
            "type": "boolean"
          },
          "doneAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "doneBy": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdBy": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "notes",
          "assigneeIds",
          "dueKind",
          "dueDate",
          "time",
          "recurrence",
          "done",
          "doneAt",
          "doneBy",
          "createdBy",
          "createdAt"
        ],
        "additionalProperties": false
      },
      "TaskRecurrence": {
        "type": "object",
        "properties": {
          "frequency": {
            "type": "string",
            "enum": [
              "daily",
              "weekly",
              "monthly",
              "yearly"
            ]
          },
          "interval": {
            "default": 1,
            "type": "integer",
            "minimum": 1,
            "maximum": 1000
          },
          "afterCompletion": {
            "default": false,
            "description": "Count the next due date from the day it was done (e.g. change the water filter 60 days after the last change).",
            "type": "boolean"
          }
        },
        "required": [
          "frequency",
          "interval",
          "afterCompletion"
        ],
        "additionalProperties": false,
        "description": "Repeating task: completing it moves the due date forward instead of closing it."
      },
      "List": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "shopping",
              "todo"
            ]
          },
          "openCount": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Items not ticked off yet."
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "type",
          "openCount",
          "createdAt"
        ],
        "additionalProperties": false,
        "description": "A shared list (shopping or to-do)."
      },
      "ListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "checked": {
            "type": "boolean"
          },
          "category": {
            "type": "string",
            "description": "Shopping aisle (dairy, produce, …) or other."
          },
          "createdBy": {
            "type": [
              "string",
              "null"
            ]
          },
          "checkedBy": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "text",
          "checked",
          "category",
          "createdBy",
          "checkedBy",
          "createdAt"
        ],
        "additionalProperties": false
      },
      "Document": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "description": "invoice, contract, insurance, bank, tax, payslip, medical, school, authority, warranty, receipt, letter, other"
          },
          "fileName": {
            "type": "string"
          },
          "mimeType": {
            "type": "string"
          },
          "size": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Bytes."
          },
          "documentDate": {
            "description": "YYYY-MM-DD: set by hand, else read by the AI.",
            "type": [
              "string",
              "null"
            ]
          },
          "notes": {
            "type": "string"
          },
          "sha256": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdBy": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ]
          },
          "analysis": {
            "$ref": "#/components/schemas/DocumentAnalysis"
          }
        },
        "required": [
          "id",
          "title",
          "category",
          "fileName",
          "mimeType",
          "size",
          "documentDate",
          "notes",
          "sha256",
          "createdBy",
          "createdAt",
          "analysis"
        ],
        "additionalProperties": false,
        "description": "A stored file (PDF or image) with its metadata and AI analysis."
      },
      "DocumentAnalysis": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "description": "none, pending, done, error, refused, unsupported, tooLarge, off, noCredits or quotaExceeded."
          },
          "summary": {
            "type": [
              "string",
              "null"
            ]
          },
          "issuer": {
            "type": [
              "string",
              "null"
            ]
          },
          "result": {
            "anyOf": [
              {
                "type": "object",
                "propertyNames": {
                  "type": "string"
                },
                "additionalProperties": {}
              },
              {
                "type": "null"
              }
            ],
            "description": "Full AI result: payment (payee, amount, IBAN, due date), contract, deadlines, events, tasks, tags."
          }
        },
        "required": [
          "status",
          "summary",
          "issuer",
          "result"
        ],
        "additionalProperties": false
      },
      "SearchHit": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "Where it lives: events, tasks, lists, notes, documents, contracts, …"
          },
          "id": {
            "type": "string",
            "description": "Id in that collection (for documents: use with get_document)."
          },
          "title": {
            "type": "string"
          },
          "snippet": {
            "type": "string"
          },
          "score": {
            "type": "number",
            "description": "Similarity 0–1, higher is closer."
          }
        },
        "required": [
          "type",
          "id",
          "title",
          "snippet",
          "score"
        ],
        "additionalProperties": false
      },
      "ButlerAction": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "addListItems, createTask, createEvent, createNote, createBill or addMeal."
          }
        },
        "required": [
          "type"
        ],
        "additionalProperties": {},
        "description": "Something the butler proposes to create, with its fields."
      },
      "Error": {
        "$ref": "#/components/schemas/Error"
      }
    },
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "lb_live_…",
        "description": "Create a key in the app under Settings → API & integrations. Scopes: `calendar:read` (Read appointments), `calendar:write` (Create, change and delete appointments), `tasks:read` (Read tasks), `tasks:write` (Create, change, complete and delete tasks), `lists:read` (Read lists and their items), `lists:write` (Create lists, add, tick off and remove items), `documents:read` (Search, read and download documents), `documents:write` (Upload, edit, analyse and delete documents), `search` (Smart search across the workspace (needs AI turned on)), `butler` (Ask the butler (uses the workspace owner's credits))."
      }
    }
  }
}
