{"openapi":"3.0.3","info":{"title":"Kangram REST API","version":"1.0.0","description":"Task tracker API. All endpoints require Bearer token authentication using a Kangram API key (`kgrm_...`). Keys are managed in the Kangram settings UI.\n\nEach operation documents the equivalent MCP tool and CLI command."},"servers":[{"url":"/api/v1","description":"Kangram API"}],"paths":{"/boards":{"get":{"operationId":"listBoards","summary":"List boards available to the authenticated user.","description":"Use this command to discover boards before creating or filtering tasks.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `list_boards`\n- **CLI:** `list-boards`, `boards`","tags":["Boards"],"parameters":[{"name":"include_archived","in":"query","required":false,"schema":{"type":"boolean"},"description":"Include archived boards in result."},{"name":"only_archived","in":"query","required":false,"schema":{"type":"boolean"},"description":"Return only archived boards."},{"name":"limit","in":"query","required":false,"schema":{"type":"number","format":"int64"},"description":"Optional max number of boards to return."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/listBoardsResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"post":{"operationId":"createBoard","summary":"Create board in a group chat with default statuses.","description":"Use this command to initialize a board and its default status workflow.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `create_board`\n- **CLI:** `create-board`","tags":["Boards"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"groupChatId":{"type":"number","format":"int64","description":"Optional target group chat id. Defaults to active context group chat."},"title":{"type":"string","description":"Optional board title."},"timezone":{"type":"string","description":"Optional board timezone (e.g. Australia/Melbourne)."},"namespaceSlug":{"type":"string","description":"Optional target namespace slug (e.g. 'kangram', 'exemplarov'). Creates the board in that namespace instead of the personal one. Use list_namespaces to discover available slugs."}}}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/createBoardResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}":{"patch":{"operationId":"updateBoard","summary":"Update a board's title, code, and/or its agent prompt.","description":"Use this to edit board metadata (title, code) and/or the board-level agent prompt. The prompt is the markdown instructions an agent reads when operating on this board (stored as the root file \"AGENTS.md\"). Pass only the fields you want to change; omitted fields are left untouched. Pass an empty string as prompt to clear the prompt.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `update_board`\n- **CLI:** `update-board`","tags":["Boards"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to update."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"New board title. Omit to leave unchanged."},"code":{"type":"string","description":"New board code (3 letters or digits A-Z/0-9, unique within the namespace). Omit to leave unchanged."},"visibility":{"type":"string","enum":["private","public"],"description":"Set board visibility. 'private' (default) = members-only; 'public' = anyone with the link can view the board read-only (no account required). Owner/admin only. Omit to leave unchanged."},"prompt":{"type":"string","description":"Markdown agent prompt for this board (stored as the root \"AGENTS.md\" file). Omit to leave unchanged; pass an empty string to clear. May include YAML frontmatter."}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/updateBoardResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/namespaces/{namespaceSlug}/boards/{boardCode}":{"get":{"operationId":"getBoardByNamespace","summary":"Get a board by its owner namespace slug and 3-character board code.","description":"Canonical lookup for a board. Resolves the namespace by slug, then the board by its 3-character code within that namespace. Membership-gated: returns an error for unknown namespace, unknown board, or non-member (indistinguishable).\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `get_board_by_namespace`\n- **CLI:** `get-board-by-namespace`","tags":["Default"],"parameters":[{"name":"namespaceSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Owner namespace slug (e.g. a username)."},{"name":"boardCode","in":"path","required":true,"schema":{"type":"string"},"description":"3-character board code (case-insensitive; legacy codes may contain Unicode letters or digits)."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/getBoardByNamespaceResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/archive":{"patch":{"operationId":"archiveBoard","summary":"Archive board (recoverable).","description":"Use this to hide a board from active workflows without deleting it.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `archive_board`\n- **CLI:** `archive-board`","tags":["Boards"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to archive."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/archiveBoardResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/restore":{"patch":{"operationId":"restoreBoard","summary":"Restore archived board.","description":"Use this to recover a previously archived board.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `restore_board`\n- **CLI:** `restore-board`","tags":["Boards"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to restore."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/restoreBoardResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/clone":{"post":{"operationId":"cloneBoard","summary":"Clone a board as a template (statuses + prompt, no tasks).","description":"Clone a board into a new board, copying the workflow not the data: statuses + board files (the prompt / agent instructions) + board title. Excludes tasks, comments, and members. The caller becomes the owner of the fresh board. The new board is created in the caller's personal namespace with a fresh unique code. Authorize: caller needs read access to the source board — a board member OR any viewer when the board is public (public boards are forkable by anyone). Authorization is enforced imperatively in execute.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `clone_board`\n- **CLI:** `clone-board`","tags":["Boards"],"parameters":[{"name":"sourceBoardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to clone the workflow from."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"Optional title for the new board. Defaults to \"<source title> (copy)\"."},"code":{"type":"string","description":"Optional 3-character code (A-Z/0-9) for the new board; must be unique in your namespace. Auto-generated if omitted."}}}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/cloneBoardResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/tasks":{"post":{"operationId":"createTask","summary":"Create a new task in the target board.","description":"Use this to add a task. Provide boardId for deterministic routing; otherwise active board is used.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `create_task`\n- **CLI:** `create-task`, `add-task`","tags":["Tasks"],"parameters":[{"name":"boardId","in":"path","required":false,"schema":{"type":"number","format":"int64"},"description":"Board ID where the task should be created."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"Short task title. Keep it clear and action-oriented."},"description":{"type":"string","description":"Optional longer task details."},"priority":{"type":"string","enum":["Critical","Major","Normal","Low"],"description":"Optional task priority: critical, major, normal, or low."},"assigneeUsername":{"type":"string","description":"Assignee username without @."},"tags":{"type":"array","items":{"type":"string"},"description":"Optional list of tags."},"statusName":{"type":"string","description":"Optional initial status name for the task."},"telegramMessageId":{"type":"number","format":"int64","description":"Optional Telegram message id for message-task linking."},"telegramChatId":{"type":"number","format":"int64","description":"Optional Telegram chat id for message-task linking."},"parentTaskNumber":{"type":"number","format":"int64","description":"Optional parent task number to create a subtask. Use with parent_board_id or board_id."},"parentBoardId":{"type":"number","format":"int64","description":"Board ID of the parent task. Defaults to board_id if omitted."}},"required":["title"]}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/createTaskResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"get":{"operationId":"listTasks","summary":"List tasks in a board with optional filtering.","description":"Use this to inspect task backlog by board, assignee, status, priority, tags, title substring, creation date range, and deletion state.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `list_tasks`\n- **CLI:** `list-tasks`, `tasks`","tags":["Tasks"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to list tasks from."},{"name":"assignee","in":"query","required":false,"schema":{"type":"string"},"description":"Optional assignee username filter (without @)."},{"name":"status","in":"query","required":false,"schema":{"type":"string"},"description":"Optional status name filter."},{"name":"include_deleted","in":"query","required":false,"schema":{"type":"boolean"},"description":"Include deleted tasks in the result."},{"name":"only_deleted","in":"query","required":false,"schema":{"type":"boolean"},"description":"Return only deleted tasks."},{"name":"tags","in":"query","required":false,"schema":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"description":"Optional list of tags to filter by. Tasks matching ANY of the specified tags are returned."},{"name":"priority","in":"query","required":false,"schema":{"oneOf":[{"type":"string","enum":["Critical","Major","Normal","Low"]},{"type":"string","enum":["high"]},{"type":"string","enum":["middle"]}]},"description":"Optional priority filter: critical, major, normal, low (aliases: high→major, middle→normal)."},{"name":"title_contains","in":"query","required":false,"schema":{"type":"string"},"description":"Optional case-insensitive substring match on task title."},{"name":"created_from","in":"query","required":false,"schema":{"type":"string"},"description":"Optional inclusive lower bound on createdAt as YYYY-MM-DD."},{"name":"created_to","in":"query","required":false,"schema":{"type":"string"},"description":"Optional inclusive upper bound on createdAt as YYYY-MM-DD."},{"name":"limit","in":"query","required":false,"schema":{"type":"number","format":"int64"},"description":"Optional max number of tasks to return."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/listTasksResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/tasks/{taskNumber}":{"get":{"operationId":"getTask","summary":"Get full task details by board and task number.","description":"Use this to read one task including its description, deadline, tags, status, and assignee.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `get_task`\n- **CLI:** `get-task`","tags":["Tasks"],"parameters":[{"name":"taskNumber","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Task number in board scope."},{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID where the task belongs."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/getTaskResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"patch":{"operationId":"updateTask","summary":"Update mutable task fields.","description":"Use this to edit task title/description/deadline/tags/assignee/status.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `update_task`\n- **CLI:** `update-task`","tags":["Tasks"],"parameters":[{"name":"taskNumber","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Task number in board scope."},{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID where the task belongs."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"New title."},"description":{"type":"string","description":"New description."},"deadline":{"type":"string","description":"New deadline string."},"priority":{"type":"string","enum":["Critical","Major","Normal","Low"],"description":"Set priority: critical, major, normal, or low."},"tags":{"type":"array","items":{"type":"string"},"description":"Replace task tags list."},"assigneeUsername":{"type":"string","description":"Assign by username (without @)."},"statusName":{"type":"string","description":"Set status by name."}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/updateTaskResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"delete":{"operationId":"deleteTask","summary":"Soft-delete task.","description":"Use this to mark a task as deleted without permanent removal.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `delete_task`\n- **CLI:** `delete-task`","tags":["Tasks"],"parameters":[{"name":"taskNumber","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Task number in board scope."},{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID where the task belongs."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/deleteTaskResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/tags":{"get":{"operationId":"listBoardTags","summary":"List distinct tags used on tasks in a board.","description":"Use this to discover which tags already exist on a board before filtering with list_tasks. Returns unique tag strings (first-seen casing), sorted case-insensitively.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `list_board_tags`\n- **CLI:** `list-board-tags`, `board-tags`","tags":["Boards"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to list tags from."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/listBoardTagsResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/tasks/{taskNumber}/status":{"patch":{"operationId":"transitionTaskStatus","summary":"Transition task to another status.","description":"Use this for explicit status moves while keeping other fields unchanged.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `transition_task_status`\n- **CLI:** `set-task-status`, `transition-task-status`","tags":["Tasks"],"parameters":[{"name":"taskNumber","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Task number in board scope."},{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID where the task belongs."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"statusName":{"type":"string","description":"Target status name."}},"required":["statusName"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/transitionTaskStatusResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/tasks/{taskNumber}/move":{"patch":{"operationId":"moveTask","summary":"Move a task from one board to another.","description":"Use this to transfer a task between boards. The task gets a new number in the target board. Status is reset to target board's default if the current status doesn't exist there.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `move_task`\n- **CLI:** `move-task`","tags":["Tasks"],"parameters":[{"name":"taskNumber","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Task number in the source board."},{"name":"sourceBoardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID where the task currently belongs."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"targetBoardId":{"type":"number","format":"int64","description":"Board ID to move the task to."}},"required":["targetBoardId"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/moveTaskResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/tasks/{taskNumber}/restore":{"patch":{"operationId":"restoreTask","summary":"Restore a previously soft-deleted task.","description":"Use this with list_tasks onlyDeleted/includeDeleted to recover deleted tasks.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `restore_task`\n- **CLI:** `restore-task`","tags":["Tasks"],"parameters":[{"name":"taskNumber","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Deleted task number in board scope."},{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID where the task belongs."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/restoreTaskResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/tasks/{taskNumber}/activity":{"get":{"operationId":"listTaskActivity","summary":"Get the activity log for a specific task.","description":"Use this to read the history of actions performed on a task (create, update, status changes, comments). Returns a timeline of activity entries.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `list_task_activity`\n- **CLI:** `task-activity`","tags":["Tasks"],"parameters":[{"name":"taskNumber","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Task number in board scope."},{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID where the task belongs."},{"name":"limit","in":"query","required":false,"schema":{"type":"number","format":"int64"},"description":"Optional max number of activity entries to return (default 20)."},{"name":"offset","in":"query","required":false,"schema":{"type":"number","format":"int64"},"description":"Optional offset for pagination (default 0)."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/listTaskActivityResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/search/tasks":{"get":{"operationId":"searchTasks","summary":"Search tasks across all boards you have access to.","description":"Use this to find tasks by text, assignee, status, priority, or attention category across all your accessible boards. All filters are optional — combine them to narrow results. Returns up to 50 tasks ordered by last updated.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `search_tasks`\n- **CLI:** `search`","tags":["Default"],"parameters":[{"name":"query","in":"query","required":false,"schema":{"type":"string"},"description":"Search query text (matches task title and description)."},{"name":"assigneeId","in":"query","required":false,"schema":{"type":"number","format":"int64"},"description":"Filter by assignee user ID."},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["open","done"]},"description":"Filter by completion status: 'open' (not done) or 'done'."},{"name":"priority","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by priority: critical, major, normal, or low."},{"name":"attention","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by attention category: overdue, due_soon, blocked, stale, unassigned."},{"name":"boardId","in":"query","required":false,"schema":{"type":"number","format":"int64"},"description":"Scope to a specific board ID."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/searchTasksResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/statuses":{"get":{"operationId":"listStatuses","summary":"List statuses for a board.","description":"Use this command to inspect the board status catalog and ordering.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `list_statuses`\n- **CLI:** `list-statuses`, `statuses`","tags":["Statuses"],"parameters":[{"name":"boardId","in":"path","required":false,"schema":{"type":"number","format":"int64"},"description":"Optional board ID. Defaults to user's active board."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/listStatusesResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"post":{"operationId":"createStatus","summary":"Create a custom status in a board.","description":"Use this command to add new statuses to board workflow.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `create_status`\n- **CLI:** `create-status`","tags":["Statuses"],"parameters":[{"name":"boardId","in":"path","required":false,"schema":{"type":"number","format":"int64"},"description":"Optional board ID. Defaults to user's active board."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Status display name."},"code":{"type":"string","description":"Optional machine code. If omitted, derived from name."},"color":{"type":"string","description":"Optional hex color, e.g. #FF9800."},"index":{"type":"number","format":"int64","description":"Optional sort index; lower appears earlier."}},"required":["name"]}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/createStatusResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/statuses/{statusId}":{"patch":{"operationId":"updateStatus","summary":"Update status fields.","description":"Update status by statusId or by boardId+code.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `update_status`\n- **CLI:** `update-status`","tags":["Statuses"],"parameters":[{"name":"statusId","in":"path","required":false,"schema":{"type":"number","format":"int64"},"description":"Target status ID."},{"name":"boardId","in":"path","required":false,"schema":{"type":"number","format":"int64"},"description":"Board ID for board+code lookup."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","description":"Existing status code for board+code lookup."},"name":{"type":"string","description":"New display name."},"newCode":{"type":"string","description":"New machine code value."},"color":{"type":"string","description":"New hex color."},"index":{"type":"number","format":"int64","description":"New sort index."}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/updateStatusResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"delete":{"operationId":"deleteStatus","summary":"Delete a status, with optional task reassignment.","description":"Delete by statusId or boardId+code. If tasks use it, provide replacementStatusId.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `delete_status`\n- **CLI:** `delete-status`","tags":["Statuses"],"parameters":[{"name":"statusId","in":"path","required":false,"schema":{"type":"number","format":"int64"},"description":"Target status ID."},{"name":"boardId","in":"path","required":false,"schema":{"type":"number","format":"int64"},"description":"Board ID for board+code lookup."},{"name":"code","in":"query","required":false,"schema":{"type":"string"},"description":"Status code for board+code lookup."},{"name":"replacementStatusId","in":"query","required":false,"schema":{"type":"number","format":"int64"},"description":"Replacement status ID when deleting an in-use status."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/deleteStatusResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/statuses/reorder":{"put":{"operationId":"reorderStatuses","summary":"Reorder statuses by explicit ID order.","description":"Provide orderedStatusIds to set deterministic status ordering for a board.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `reorder_statuses`\n- **CLI:** `reorder-statuses`","tags":["Statuses"],"parameters":[{"name":"boardId","in":"path","required":false,"schema":{"type":"number","format":"int64"},"description":"Optional board ID. Defaults to user's active board."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"orderedStatusIds":{"type":"array","items":{"type":"number","format":"int64"},"description":"Status IDs in desired order."}},"required":["orderedStatusIds"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/reorderStatusesResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/tasks/{taskNumber}/comments":{"post":{"operationId":"addComment","summary":"Add a comment to a task.","description":"Use this to add a comment to a specific task. Provide board_id + task_number to identify the task.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `add_comment`\n- **CLI:** `add-comment`","tags":["Comments"],"parameters":[{"name":"taskNumber","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Task number in board scope."},{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID where the task belongs."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","description":"Comment text."}},"required":["text"]}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/addCommentResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"get":{"operationId":"listComments","summary":"List comments on a task.","description":"Use this to retrieve all comments for a specific task. Provide board_id + task_number.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `list_comments`\n- **CLI:** `list-comments`","tags":["Comments"],"parameters":[{"name":"taskNumber","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Task number in board scope."},{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID where the task belongs."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/listCommentsResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/tasks/{taskNumber}/comments/{commentId}":{"delete":{"operationId":"deleteComment","summary":"Delete your own comment from a task.","description":"Use this to delete a comment. Allowed for the comment author or a board admin (owner/admin). Provide board_id + task_number for context and comment_id.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `delete_comment`\n- **CLI:** `delete-comment`","tags":["Comments"],"parameters":[{"name":"commentId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"ID of the comment to delete."},{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID where the task belongs."},{"name":"taskNumber","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Task number in board scope."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/deleteCommentResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/tasks/{taskNumber}/checklist":{"post":{"operationId":"addChecklistItem","summary":"Add a checklist item to a task.","description":"Use this to add a new item to a task's checklist. Provide board_id + task_number to identify the task.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `add_checklist_item`\n- **CLI:** `add-checklist-item`","tags":["Checklist"],"parameters":[{"name":"taskNumber","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Task number in board scope."},{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID where the task belongs."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"Checklist item text."}},"required":["title"]}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/addChecklistItemResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"get":{"operationId":"listChecklist","summary":"List checklist items on a task.","description":"Use this to retrieve all checklist items for a specific task. Provide board_id + task_number.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `list_checklist`\n- **CLI:** `list-checklist`","tags":["Checklist"],"parameters":[{"name":"taskNumber","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Task number in board scope."},{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID where the task belongs."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/listChecklistResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/tasks/{taskNumber}/checklist/{itemId}":{"patch":{"operationId":"updateChecklistItem","summary":"Update a checklist item (toggle done, rename).","description":"Use this to update a checklist item's title or done status. Provide item_id and fields to update.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `update_checklist_item`\n- **CLI:** `update-checklist-item`","tags":["Checklist"],"parameters":[{"name":"itemId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Checklist item ID."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"New title for the item."},"done":{"type":"boolean","description":"Set done status (true/false)."}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/updateChecklistItemResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"delete":{"operationId":"deleteChecklistItem","summary":"Delete a checklist item.","description":"Use this to remove a checklist item from a task. Provide item_id.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `delete_checklist_item`\n- **CLI:** `delete-checklist-item`","tags":["Checklist"],"parameters":[{"name":"itemId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Checklist item ID to delete."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/deleteChecklistItemResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/members":{"get":{"operationId":"listBoardMembers","summary":"List members of a board with their roles.","description":"Use this command to see all board members and their roles (owner/admin/user).\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `list_board_members`\n- **CLI:** `list-board-members`","tags":["Board Members"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to list members for."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/listBoardMembersResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"post":{"operationId":"addBoardMember","summary":"Add a member directly to a board by Telegram username (no invitation/accept step).","description":"Use this command to add a user directly to a board — they become a member immediately, with no invitation to accept. This is the one-step grant (the bot /addmember command). Owner/admin only; cannot create or assign the owner role.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `add_board_member`\n- **CLI:** `add-board-member`","tags":["Board Members"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to add the user to."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"username":{"type":"string","description":"Telegram username of the user to add (without @)."},"role":{"type":"string","enum":["admin","user"],"description":"Role to assign (admin or user). Default: user. Cannot assign owner role."}},"required":["username"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/addBoardMemberResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/members/invite":{"post":{"operationId":"inviteBoardMember","summary":"Invite a user to a board by Telegram username.","description":"Use this command to invite a user to a board. The invited user will receive a notification and must accept. Owner/admin only.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `invite_board_member`\n- **CLI:** `invite-board-member`","tags":["Board Members"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to invite the user to."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"username":{"type":"string","description":"Telegram username of the user to invite (without @)."},"role":{"type":"string","enum":["admin","user"],"description":"Role to assign (admin or user). Default: user. Cannot assign owner role."}},"required":["username"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/inviteBoardMemberResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/members/{userId}":{"delete":{"operationId":"removeBoardMember","summary":"Remove a member from a board (or revoke their elevated role).","description":"Use this command to remove a member from a board. On group-chat-linked boards, removing a member with an explicit board_member row reverts them to a regular Telegram member (they stay on the board via the linked group). Members without a board_member row (Telegram-only) cannot be removed. Owner can remove admin/user, admin can remove user. Cannot remove owner.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `remove_board_member`\n- **CLI:** `remove-board-member`","tags":["Board Members"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to remove the user from."},{"name":"userId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"User ID to remove from the board."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/removeBoardMemberResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"patch":{"operationId":"updateMemberRole","summary":"Change a board member's role (admin/user).","description":"Use this command to change an existing board member's role. Owner/admin only. Cannot target the board owner or promote anyone to owner.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `update_member_role`\n- **CLI:** `update-member-role`","tags":["Board Members"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID where the member belongs."},{"name":"userId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"User ID of the member whose role to change."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","enum":["admin","user"],"description":"New role to assign (admin or user). Cannot assign owner."}},"required":["role"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/updateMemberRoleResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/invitations":{"get":{"operationId":"listPendingInvitations","summary":"List pending board invitations (yours or for a specific board).","description":"Use this without board_id to see your pending invitations. With board_id, see pending invitations for that board (must be a member).\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `list_pending_invitations`\n- **CLI:** `list-invitations`","tags":["Invitations"],"parameters":[{"name":"boardId","in":"query","required":false,"schema":{"type":"number","format":"int64"},"description":"Optional board ID to filter invitations for. If omitted, shows your pending invitations."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/listPendingInvitationsResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/invitations/{token}":{"patch":{"operationId":"respondToInvitation","summary":"Accept or reject a board invitation.","description":"Use this command to accept or reject a pending board invitation by its token (from list_pending_invitations).\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `respond_to_invitation`\n- **CLI:** `respond-invitation`","tags":["Invitations"],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"},"description":"Invitation token (the unguessable bearer string from list_pending_invitations)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"accept":{"type":"boolean","description":"True to accept, false to reject."}},"required":["accept"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/respondToInvitationResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/invitations/{invitationId}":{"delete":{"operationId":"cancelBoardInvitation","summary":"Cancel a pending board invitation.","description":"Use this command to cancel a pending board invitation. Only the original inviter or a board admin can cancel.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `cancel_board_invitation`\n- **CLI:** `cancel-invitation`","tags":["Invitations"],"parameters":[{"name":"invitationId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Invitation ID to cancel."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/cancelBoardInvitationResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/organizations":{"post":{"operationId":"createOrganization","summary":"Create an organization with its own namespace.","description":"Create a new organization. The organization gets its own namespace (slug derived from the name). The creator becomes the organization owner. Use this when a user asks to create a namespace, organization, or workspace.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `create_organization`\n- **CLI:** `create-organization`","tags":["Default"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Organization name (e.g. 'Kangram', 'Acme Inc'). A namespace slug is derived from this."}},"required":["name"]}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/createOrganizationResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/namespaces":{"get":{"operationId":"listNamespaces","summary":"List namespaces visible to the current user.","description":"List all namespaces the user can see: their personal namespace plus any organization namespaces they own or are a member of. Use this to discover where boards can be created or moved.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `list_namespaces`\n- **CLI:** `list-namespaces`","tags":["Default"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/listNamespacesResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/move":{"post":{"operationId":"moveBoard","summary":"Move a board to a different namespace.","description":"Move a board from its current namespace to a target namespace. The board's 3-character code must be unique in the target namespace. The board URL will change. Use this to consolidate boards into an organization namespace.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `move_board`\n- **CLI:** `move-board`","tags":["Boards"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to move."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"namespaceSlug":{"type":"string","description":"Target namespace slug (e.g. 'kangram'). Use list_namespaces to discover available slugs."}},"required":["namespaceSlug"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/moveBoardResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/prompt":{"get":{"operationId":"getBoardPrompt","summary":"Get a board's agent prompt (root file content).","description":"Fetch the board-level agent prompt — the markdown instructions an agent should follow when operating on this board. Read this into your context before working a board. Returns the content of the board's root file (\"AGENTS.md\"); null when no prompt is set.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `get_board_prompt`\n- **CLI:** `get-board-prompt`","tags":["Boards"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to read the prompt for."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/getBoardPromptResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/files":{"put":{"operationId":"updateBoardFile","summary":"Create or update a named board file (multi-file-ready prompt store).","description":"Upsert a named markdown file on a board. In v1 the conventional name is \"AGENTS.md\" (the root prompt). Omit content (or pass empty) to clear a file's body. Future versions will support multiple named files; this command is the low-level writer beneath update_board's prompt option.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `update_board_file`\n- **CLI:** `update-board-file`","tags":["Boards"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to write the file on."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"File name (path-like identifier). Use \"AGENTS.md\" for the root prompt."},"content":{"type":"string","description":"Markdown content. Omit or pass empty to clear the file body."},"format":{"type":"string","description":"File format. Defaults to \"markdown\"."}},"required":["name"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/updateBoardFileResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"get":{"operationId":"listBoardFiles","summary":"List all named files attached to a board.","description":"List the board's named files (the multi-file-ready prompt store). v1 returns at least the root \"AGENTS.md\" once a prompt has been set; empty list means no prompt/files yet.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `list_board_files`\n- **CLI:** `list-board-files`","tags":["Boards"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to list files for."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/listBoardFilesResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/oauth/clients":{"post":{"operationId":"createOAuthClient","summary":"Register an OAuth2 client application (for 'Login with Kangram').","description":"Register a new OAuth2 client so a third-party app can authenticate users via 'Login with Kangram'. Returns the client_id and a client_secret shown ONCE — store it securely. Owner-only.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `create_oauth_client`\n- **CLI:** `create-oauth-client`","tags":["Default"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Human-readable client application name."},"redirectUris":{"type":"array","items":{"type":"string"},"description":"Allowed redirect URIs (exact match, https required; http only on localhost). No wildcards."},"scopes":{"type":"array","items":{"type":"string","enum":["profile","boards:read","boards:write","tasks:read","tasks:write"]},"description":"Scopes the client is allowed to request. Defaults to ['profile']."}},"required":["name","redirectUris"]}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/createOAuthClientResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"get":{"operationId":"listOAuthClients","summary":"List your OAuth2 client applications.","description":"List the OAuth2 clients you own (client_id, name, redirect URIs, scopes, revocation status).\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `list_oauth_clients`\n- **CLI:** `list-oauth-clients`","tags":["Default"],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/listOAuthClientsResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/oauth/clients/{clientId}":{"delete":{"operationId":"revokeOAuthClient","summary":"Revoke an OAuth2 client application (disables future authorization).","description":"Revoke one of your OAuth2 clients by its numeric ID. Existing tokens are not deleted but no new authorizations will be allowed.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `revoke_oauth_client`\n- **CLI:** `revoke-oauth-client`","tags":["Default"],"parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Numeric ID of the OAuth2 client to revoke."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/revokeOAuthClientResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/session-handoff":{"post":{"operationId":"saveSessionHandoff","summary":"Save an end-of-session handoff note to a board (remembers where you left off).","description":"Save a session handoff — a durable note on the board recording where the work stands: what was done, what is next, what is blocked, and key links (PRs, issues, branches). Call this at the END of a working session so the next session (possibly a brand-new chat) can pick up exactly where you left off. Use this when the user says 'remember where we left off', 'save our progress', 'save the session state', or 'don't lose this context'. `summary` must be YOUR OWN concise authored recap — never a transcript or list of raw messages.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `save_session_handoff`\n- **CLI:** `save-handoff`, `handoff`","tags":["Boards"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID the handoff belongs to."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"summary":{"type":"string","description":"Your authored recap: done / next / blocked. One concise string (max 20000 chars) — not a transcript."},"links":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Optional references — PR/issue URLs, branch names, doc links (e.g. ['https://github.com/o/r/pull/12', 'feat/auth-refactor']). Max 25 single-line items."}},"required":["summary"]}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/saveSessionHandoffResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/project-context":{"get":{"operationId":"getProjectContext","summary":"Reconstruct a board's working state: handoff, attention, top tasks, recent activity.","description":"Get the full project context for a board — everything needed to CONTINUE work without re-explaining: the latest session handoff (where we left off), an attention snapshot (blocked / overdue / due soon / unassigned / stale counts), the top open tasks, and recent board activity. Call this at the START of a session when the user says 'continue where we left off', 'what's the state of the project', 'resume our work', or 'remind me what we were doing' — especially in a NEW chat after a previous session saved a handoff.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `get_project_context`\n- **CLI:** `project-context`, `get-project-context`","tags":["Boards"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to load context for."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/getProjectContextResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/settings":{"get":{"operationId":"getBoardSettings","summary":"Get effective board settings (one key, or all).","description":"Use this command to read a board's effective settings — the stored value, or the default when unset (lazy). Pass a key to read one setting; omit it to read all. Returns { key: value } object(s).\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `get_board_settings`\n- **CLI:** `get-board-settings`","tags":["Boards"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to read settings for."},{"name":"key","in":"query","required":false,"schema":{"type":"string"},"description":"Optional setting key (e.g. \"autoAddAssignees\"). Omit to read all settings."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/getBoardSettingsResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/{boardId}/settings/{key}":{"put":{"operationId":"setBoardSetting","summary":"Set a board setting (owner/admin only).","description":"Use this command to change a board setting. The value is a string coerced to the setting's type server-side (booleans accept on/off, true/false, 1/0, yes/no). Use get_board_settings_schema to discover available keys and types. Example: set autoAddAssignees to \"off\" to require explicit /addmember on task assignment.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `set_board_setting`\n- **CLI:** `set-board-setting`","tags":["Boards"],"parameters":[{"name":"boardId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"Board ID to configure."},{"name":"key","in":"path","required":true,"schema":{"type":"string"},"description":"Setting key (e.g. \"autoAddAssignees\")."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"value":{"type":"string","description":"New value as a string (coerced to the setting's type). Booleans: on/off, true/false, 1/0."}},"required":["value"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/setBoardSettingResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/board-settings-schema":{"get":{"operationId":"getBoardSettingsSchema","summary":"Get the schema of available board settings (keys, types, defaults).","description":"Use this command to discover which board settings exist and their types/defaults (json-schema-like). Pass a key to inspect one setting; omit for all. Board-independent metadata — call this before set_board_setting to learn valid keys and types.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `get_board_settings_schema`\n- **CLI:** `get-board-settings-schema`","tags":["Default"],"parameters":[{"name":"key","in":"query","required":false,"schema":{"type":"string"},"description":"Optional setting key to inspect. Omit for all available settings."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/getBoardSettingsSchemaResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/boards/bind":{"post":{"operationId":"bindBoardToGroup","summary":"Bind a board to a Telegram group chat.","description":"Bind (link) a board to a Telegram group chat. The board becomes the group's primary board — bot commands in the group will act on this board. Unbinds any previous binding first. The actor must be an owner/admin of the target board. Use this when a user asks to set, link, bind, or assign a board to a chat/group. boardRef accepts: 'ns/code' (e.g. 'kangram/DEV'), a code alone (uses the active namespace), or a full URL like 'https://kangram.app/#/kangram/DEV'.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `bind_board_to_group`\n- **CLI:** `bind-board-to-group`","tags":["Boards"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"boardRef":{"type":"string","description":"Board reference: 'ns/code' (e.g. 'kangram/DEV'), 'code' alone, or a kangram.app URL."},"groupChatId":{"type":"number","format":"int64","description":"Telegram group chat ID. Omit in a Telegram group context — the current group is auto-detected."}},"required":["boardRef"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/bindBoardToGroupResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/organizations/{namespaceSlug}/agents":{"post":{"operationId":"createAgent","summary":"Create an agent account inside an organization.","description":"Create a non-human agent account (User type='agent') inside the organization identified by its namespace slug. The agent becomes an org member immediately (board access via role inheritance), gets no personal namespace and cannot log in. A first API key is auto-issued and returned in plainKey — show/store it now, it is never shown again. Requires organization owner/admin.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `create_agent`\n- **CLI:** `create-agent`","tags":["Default"],"parameters":[{"name":"namespaceSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Namespace slug of the organization (e.g. 'kangram' for kangram.app/kangram)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"username":{"type":"string","description":"Unique username for the agent (letters, digits, dot, dash, underscore). Used for invites and search."},"displayName":{"type":"string","description":"Human-readable display name. Defaults to the username."},"role":{"type":"string","enum":["admin","member"],"description":"Organization role. 'member' (default) maps to board user; 'admin' maps to board admin. Agents never own orgs."}},"required":["username"]}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/createAgentResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"get":{"operationId":"listAgents","summary":"List organization members (agents flagged).","description":"List the members of the organization identified by its namespace slug, including agent accounts (type='agent') with their active API-key counts and last key use. Requires organization owner/admin.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `list_agents`\n- **CLI:** `list-agents`","tags":["Default"],"parameters":[{"name":"namespaceSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Namespace slug of the organization."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/listAgentsResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/organizations/{namespaceSlug}/agents/{agentUsername}":{"delete":{"operationId":"deleteAgent","summary":"Delete an agent account from an organization.","description":"Delete an agent account: revokes all its API keys, removes memberships, unassigns its tasks, then hard-deletes the user. When history rows (messages/activity) block the hard delete, the agent is deactivated instead (zero access, row kept) and status='deactivated' is returned. Requires organization owner/admin.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `delete_agent`\n- **CLI:** `delete-agent`","tags":["Default"],"parameters":[{"name":"namespaceSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Namespace slug of the organization."},{"name":"agentUsername","in":"path","required":true,"schema":{"type":"string"},"description":"Username of the agent to delete."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/deleteAgentResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/organizations/{namespaceSlug}/agents/{agentUsername}/keys":{"post":{"operationId":"issueAgentKey","summary":"Issue a new API key for an agent account.","description":"Mint a new API key for an agent member of the organization. Use for rotation or additional keys. The plaintext key is returned once — store it immediately. Requires organization owner/admin.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `issue_agent_key`\n- **CLI:** `issue-agent-key`","tags":["Default"],"parameters":[{"name":"namespaceSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Namespace slug of the organization."},{"name":"agentUsername","in":"path","required":true,"schema":{"type":"string"},"description":"Username of the agent."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Key label. Defaults to '<username> — <date>'."},"scope":{"type":"string","enum":["readonly","taskwriter","full"],"description":"Key scope label (enforcement is planned; stored today)."}}}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/issueAgentKeyResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/agent-keys/{keyId}":{"delete":{"operationId":"revokeAgentKey","summary":"Revoke an API key belonging to an agent account.","description":"Revoke an agent's API key by id. Only keys owned by agent accounts are revocable this way (humans revoke their own). Requires organization owner/admin of an org the agent belongs to.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `revoke_agent_key`\n- **CLI:** `revoke-agent-key`","tags":["Default"],"parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"number","format":"int64"},"description":"API key id (from list output or the web UI)."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/revokeAgentKeyResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/namespaces/{namespaceSlug}/members":{"post":{"operationId":"addNamespaceMember","summary":"Add an existing user as a member of a workspace (namespace).","description":"Grant an existing user workspace-level membership (NamespaceMember row) in the namespace identified by its slug. The member immediately inherits access to the namespace's boards (explicit board membership still overrides) and may create/move boards into the namespace. Roles: 'member' (default) or 'admin'. The owner role is structural and cannot be assigned. Direct grant — no invitation to accept. Requires the workspace owner.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `add_namespace_member`\n- **CLI:** `add-namespace-member`","tags":["Default"],"parameters":[{"name":"namespaceSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Target namespace slug (e.g. 'kangram' for kangram.app/kangram)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"username":{"type":"string","description":"Username of an existing user (without @, case-insensitive)."},"role":{"type":"string","enum":["admin","member"],"description":"Workspace role: 'member' (default) or 'admin'. 'owner' is not assignable."}},"required":["username"]}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/addNamespaceMemberResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"get":{"operationId":"listNamespaceMembers","summary":"List workspace (namespace) members with roles and membership sources.","description":"List the unified member roster of a namespace: structural owner, explicitly added members (editable here), and organization-inherited members (org namespaces). Requires the workspace owner.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `list_namespace_members`\n- **CLI:** `list-namespace-members`","tags":["Default"],"parameters":[{"name":"namespaceSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Namespace slug of the workspace."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/listNamespaceMembersResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}},"/namespaces/{namespaceSlug}/members/{userId}":{"delete":{"operationId":"removeNamespaceMember","summary":"Remove a workspace (namespace) member.","description":"Remove an explicitly-granted workspace membership (NamespaceMember row). The workspace owner cannot be removed, and members inherited from the organization are not removable here (manage them on the org surface). Explicit per-board memberships deliberately survive. Requires the workspace owner.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `remove_namespace_member`\n- **CLI:** `remove-namespace-member`","tags":["Default"],"parameters":[{"name":"namespaceSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Namespace slug of the workspace."},{"name":"username","in":"query","required":false,"schema":{"type":"string"},"description":"Username of the member (without @). Either username or user_id is required."},{"name":"userId","in":"path","required":false,"schema":{"type":"number","format":"int64"},"description":"User ID of the member (from list_namespace_members). Either username or user_id is required."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/removeNamespaceMemberResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]},"patch":{"operationId":"updateNamespaceMemberRole","summary":"Change a workspace member's role (admin/member).","description":"Change the role of an explicitly-granted workspace member. The owner role is structural and cannot be assigned or changed; org-inherited members are managed on the organization surface. Requires the workspace owner.\n---\n\n**Other ways to call this:**\n\n- **MCP tool:** `update_namespace_member_role`\n- **CLI:** `update-namespace-member-role`","tags":["Default"],"parameters":[{"name":"namespaceSlug","in":"path","required":true,"schema":{"type":"string"},"description":"Namespace slug of the workspace."},{"name":"username","in":"query","required":false,"schema":{"type":"string"},"description":"Username of the member (without @). Either username or user_id is required."},{"name":"userId","in":"path","required":false,"schema":{"type":"number","format":"int64"},"description":"User ID of the member. Either username or user_id is required."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","enum":["admin","member"],"description":"New role: 'admin' or 'member'."}},"required":["role"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","example":true},"data":{"$ref":"#/components/schemas/updateNamespaceMemberRoleResponse"}},"required":["ok"]}}}},"400":{"description":"Validation or business logic error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"Authenticated but not allowed (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Target resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"State conflict (e.g. already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"security":[{"BearerAuth":[]}]}}},"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"kgrm_...","description":"API key from Kangram settings. Prefix: `kgrm_`"}},"schemas":{"listBoardsResponse":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"title":{"type":"string"},"code":{"type":"string","nullable":true},"namespaceId":{"type":"number","nullable":true},"timezone":{"type":"string","nullable":true},"archivedAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"groupChatId":{"type":"number","nullable":true}},"required":["id","title","code","namespaceId","timezone","archivedAt","createdAt","groupChatId"],"additionalProperties":true}},"ApiError":{"type":"object","properties":{"ok":{"type":"boolean","example":false},"error":{"type":"string"}},"required":["ok"]},"createBoardResponse":{"type":"object","properties":{"id":{"type":"number"},"title":{"type":"string"},"code":{"type":"string","nullable":true},"namespaceId":{"type":"number","nullable":true},"timezone":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","title","code","namespaceId","timezone","createdAt"],"additionalProperties":true},"updateBoardResponse":{"type":"object","properties":{"id":{"type":"number"},"title":{"type":"string"},"code":{"type":"string","nullable":true},"namespaceId":{"type":"number","nullable":true},"timezone":{"type":"string","nullable":true},"archivedAt":{"type":"string","nullable":true},"visibility":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","title","code","namespaceId","timezone","archivedAt","visibility","createdAt"],"additionalProperties":true},"getBoardByNamespaceResponse":{"type":"object","properties":{"id":{"type":"number"},"title":{"type":"string"},"code":{"type":"string","nullable":true},"namespaceId":{"type":"number","nullable":true},"timezone":{"type":"string","nullable":true},"archivedAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","title","code","namespaceId","timezone","archivedAt","createdAt"],"additionalProperties":true},"archiveBoardResponse":{"type":"object","properties":{"id":{"type":"number"},"title":{"type":"string"},"archivedAt":{"type":"string","nullable":true}},"required":["id","title","archivedAt"],"additionalProperties":true},"restoreBoardResponse":{"type":"object","properties":{"id":{"type":"number"},"title":{"type":"string"},"archivedAt":{"type":"string","nullable":true}},"required":["id","title","archivedAt"],"additionalProperties":true},"cloneBoardResponse":{"type":"object","properties":{"id":{"type":"number"},"title":{"type":"string"},"code":{"type":"string","nullable":true},"namespaceId":{"type":"number","nullable":true},"createdAt":{"type":"string"}},"required":["id","title","code","namespaceId","createdAt"],"additionalProperties":true},"createTaskResponse":{"type":"object","properties":{"id":{"type":"number"},"number":{"type":"number"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"priority":{"type":"string","nullable":true},"statusId":{"type":"number","nullable":true},"assigneeId":{"type":"number","nullable":true},"creatorId":{"type":"number"},"boardId":{"type":"number"},"tags":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","number","title","description","priority","statusId","assigneeId","creatorId","boardId","tags","createdAt","updatedAt"],"additionalProperties":true},"getTaskResponse":{"type":"object","properties":{"id":{"type":"number"},"number":{"type":"number"},"title":{"type":"string"},"text":{"type":"string","nullable":true},"priority":{"type":"string","nullable":true},"deadline":{"type":"string","nullable":true},"statusId":{"type":"number","nullable":true},"assigneeId":{"type":"number","nullable":true},"tags":{"type":"array","items":{"type":"string"}},"boardId":{"type":"number"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","number","title","text","priority","deadline","statusId","assigneeId","tags","boardId","createdAt","updatedAt"],"additionalProperties":true},"listTasksResponse":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"number":{"type":"number"},"title":{"type":"string"},"priority":{"type":"string","nullable":true},"statusId":{"type":"number","nullable":true},"assigneeId":{"type":"number","nullable":true},"creatorId":{"type":"number"},"boardId":{"type":"number"},"tags":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","number","title","priority","statusId","assigneeId","creatorId","boardId","tags","createdAt","updatedAt"],"additionalProperties":true}},"listBoardTagsResponse":{"type":"array","items":{"type":"string"}},"updateTaskResponse":{"type":"object","properties":{"id":{"type":"number"},"number":{"type":"number"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"priority":{"type":"string","nullable":true},"deadline":{"type":"string","nullable":true},"statusId":{"type":"number","nullable":true},"assigneeId":{"type":"number","nullable":true},"tags":{"type":"array","items":{"type":"string"}},"updatedAt":{"type":"string"}},"required":["id","number","title","description","priority","deadline","statusId","assigneeId","tags","updatedAt"],"additionalProperties":true},"transitionTaskStatusResponse":{"type":"object","properties":{"id":{"type":"number"},"number":{"type":"number"},"title":{"type":"string"},"statusId":{"type":"number","nullable":true},"updatedAt":{"type":"string"}},"required":["id","number","title","statusId","updatedAt"],"additionalProperties":true},"deleteTaskResponse":{"type":"object","properties":{"id":{"type":"number"},"number":{"type":"number"},"title":{"type":"string"},"deletedAt":{"type":"string","nullable":true}},"required":["id","number","title","deletedAt"],"additionalProperties":true},"moveTaskResponse":{"type":"object","properties":{"id":{"type":"number"},"number":{"type":"number"},"title":{"type":"string"},"boardId":{"type":"number"},"statusId":{"type":"number","nullable":true}},"required":["id","number","title","boardId","statusId"],"additionalProperties":true},"restoreTaskResponse":{"type":"object","properties":{"id":{"type":"number"},"number":{"type":"number"},"title":{"type":"string"},"deletedAt":{"type":"string","nullable":true}},"required":["id","number","title","deletedAt"],"additionalProperties":true},"listTaskActivityResponse":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"action":{"type":"string"},"entityType":{"type":"string"},"entityId":{"type":"number"},"userId":{"type":"number","nullable":true},"username":{"type":"string","nullable":true},"changes":{"nullable":true},"createdAt":{"type":"string"}},"required":["id","action","entityType","entityId","userId","username","createdAt"],"additionalProperties":true}},"searchTasksResponse":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"number":{"type":"number"},"title":{"type":"string"},"priority":{"type":"string"}},"required":["id","number","title","priority"],"additionalProperties":true}},"listStatusesResponse":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"code":{"type":"string"},"color":{"type":"string","nullable":true},"index":{"type":"number"},"boardId":{"type":"number"}},"required":["id","name","code","color","index","boardId"],"additionalProperties":true}},"createStatusResponse":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"code":{"type":"string"},"color":{"type":"string","nullable":true},"index":{"type":"number"}},"required":["id","name","code","color","index"],"additionalProperties":true},"updateStatusResponse":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"code":{"type":"string"},"color":{"type":"string","nullable":true},"index":{"type":"number"}},"required":["id","name","code","color","index"],"additionalProperties":true},"reorderStatusesResponse":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"code":{"type":"string"},"index":{"type":"number"}},"required":["id","name","code","index"],"additionalProperties":true}},"deleteStatusResponse":{"type":"object","properties":{"deletedStatusId":{"type":"number"},"reassignedTasks":{"type":"number"}},"required":["deletedStatusId","reassignedTasks"]},"addCommentResponse":{"type":"object","properties":{"id":{"type":"number"},"text":{"type":"string"},"taskId":{"type":"number"},"authorId":{"type":"number"},"createdAt":{"type":"string"}},"required":["id","text","taskId","authorId","createdAt"],"additionalProperties":true},"listCommentsResponse":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"text":{"type":"string"},"authorId":{"type":"number"},"createdAt":{"type":"string"}},"required":["id","text","authorId","createdAt"],"additionalProperties":true}},"deleteCommentResponse":{"type":"object","properties":{"id":{"type":"number"}},"required":["id"],"additionalProperties":true},"addChecklistItemResponse":{"type":"object","properties":{"id":{"type":"number"},"title":{"type":"string"},"done":{"type":"boolean"},"taskId":{"type":"number"}},"required":["id","title","done","taskId"],"additionalProperties":true},"listChecklistResponse":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"title":{"type":"string"},"done":{"type":"boolean"}},"required":["id","title","done"],"additionalProperties":true}},"updateChecklistItemResponse":{"type":"object","properties":{"id":{"type":"number"},"title":{"type":"string"},"done":{"type":"boolean"}},"required":["id","title","done"],"additionalProperties":true},"deleteChecklistItemResponse":{"type":"object","properties":{"id":{"type":"number"}},"required":["id"]},"listBoardMembersResponse":{"type":"array","items":{"type":"object","properties":{"boardId":{"type":"number"},"userId":{"type":"number"},"role":{"type":"string"}},"required":["boardId","userId","role"],"additionalProperties":true}},"inviteBoardMemberResponse":{"type":"object","properties":{"id":{"type":"number"},"boardId":{"type":"number"},"inviteeId":{"type":"number"},"invitedById":{"type":"number"},"role":{"type":"string"},"status":{"type":"string"}},"required":["id","boardId","inviteeId","invitedById","role","status"],"additionalProperties":true},"addBoardMemberResponse":{"type":"object","properties":{"boardId":{"type":"number"},"userId":{"type":"number"},"role":{"type":"string"}},"required":["boardId","userId","role"],"additionalProperties":true},"removeBoardMemberResponse":{"type":"object","properties":{"removedUserId":{"type":"number"}},"required":["removedUserId"]},"updateMemberRoleResponse":{"type":"object","properties":{"boardId":{"type":"number"},"userId":{"type":"number"},"role":{"type":"string"}},"required":["boardId","userId","role"],"additionalProperties":true},"listPendingInvitationsResponse":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"token":{"type":"string","nullable":true},"boardId":{"type":"number"},"inviteeId":{"type":"number"},"invitedById":{"type":"number"},"role":{"type":"string"},"status":{"type":"string"}},"required":["id","token","boardId","inviteeId","invitedById","role","status"],"additionalProperties":true}},"respondToInvitationResponse":{"type":"object","properties":{"id":{"type":"number"},"boardId":{"type":"number"},"status":{"type":"string"}},"required":["id","boardId","status"],"additionalProperties":true},"cancelBoardInvitationResponse":{"type":"object","properties":{"id":{"type":"number"},"boardId":{"type":"number"},"status":{"type":"string"}},"required":["id","boardId","status"],"additionalProperties":true},"createOrganizationResponse":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"slug":{"type":"string"},"namespaceId":{"type":"number"}},"required":["id","name","slug","namespaceId"],"additionalProperties":true},"listNamespacesResponse":{"type":"object","properties":{"namespaces":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"slug":{"type":"string","nullable":true},"ownerType":{"type":"string"},"ownerId":{"type":"number","nullable":true}},"required":["id","slug","ownerType","ownerId"]}}},"required":["namespaces"],"additionalProperties":true},"moveBoardResponse":{"type":"object","properties":{"id":{"type":"number"},"title":{"type":"string"},"code":{"type":"string","nullable":true},"namespaceId":{"type":"number"},"namespaceSlug":{"type":"string","nullable":true}},"required":["id","title","code","namespaceId","namespaceSlug"],"additionalProperties":true},"getBoardPromptResponse":{"type":"object","properties":{"name":{"type":"string"},"content":{"type":"string","nullable":true}},"required":["name","content"],"additionalProperties":true},"updateBoardFileResponse":{"type":"object","properties":{"id":{"type":"number"},"boardId":{"type":"number"},"name":{"type":"string"},"content":{"type":"string","nullable":true},"format":{"type":"string"},"sortOrder":{"type":"number"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","boardId","name","content","format","sortOrder","createdAt","updatedAt"],"additionalProperties":true},"listBoardFilesResponse":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"boardId":{"type":"number"},"name":{"type":"string"},"content":{"type":"string","nullable":true},"format":{"type":"string"},"sortOrder":{"type":"number"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","boardId","name","content","format","sortOrder","createdAt","updatedAt"],"additionalProperties":true}},"createOAuthClientResponse":{"type":"object","properties":{"id":{"type":"number"},"clientId":{"type":"string"},"clientSecret":{"type":"string"},"name":{"type":"string"},"redirectUris":{"type":"array","items":{"type":"string"}},"scopes":{"type":"array","items":{"type":"string"}}},"required":["id","clientId","clientSecret","name","redirectUris","scopes"],"additionalProperties":true},"listOAuthClientsResponse":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"clientId":{"type":"string"},"name":{"type":"string"},"redirectUris":{"type":"array","items":{"type":"string"}},"scopes":{"type":"array","items":{"type":"string"}}},"required":["id","clientId","name","redirectUris","scopes"],"additionalProperties":true}},"revokeOAuthClientResponse":{"type":"object","properties":{"id":{"type":"number"},"clientId":{"type":"string"},"revokedAt":{"type":"string","nullable":true}},"required":["id","clientId","revokedAt"],"additionalProperties":true},"saveSessionHandoffResponse":{"type":"object","properties":{"fileName":{"type":"string"},"updatedAt":{"type":"string"},"contentPreview":{"type":"string"}},"required":["fileName","updatedAt","contentPreview"],"additionalProperties":true},"getProjectContextResponse":{"type":"object","properties":{"board":{"type":"object","properties":{"id":{"type":"number"},"title":{"type":"string"}},"required":["id","title"]},"handoff":{"type":"object","properties":{"content":{"type":"string"},"updatedAt":{"type":"string"}},"required":["content","updatedAt"],"nullable":true},"attention":{"type":"object","additionalProperties":{"type":"number"}},"openTaskCount":{"type":"number"},"topTasks":{"type":"array","items":{}},"recentActivity":{"type":"array","items":{}}},"required":["board","handoff","attention","openTaskCount","topTasks","recentActivity"],"additionalProperties":true},"getBoardSettingsResponse":{"type":"object","properties":{},"additionalProperties":true},"setBoardSettingResponse":{"type":"object","properties":{},"additionalProperties":true},"getBoardSettingsSchemaResponse":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"type":{"type":"string"},"default":{"type":"string"}},"required":["key","type","default"],"additionalProperties":true}},"bindBoardToGroupResponse":{"type":"object","properties":{"id":{"type":"number"},"title":{"type":"string"},"code":{"type":"string","nullable":true},"groupChatId":{"type":"number","nullable":true}},"required":["id","title","code","groupChatId"],"additionalProperties":true},"createAgentResponse":{"type":"object","properties":{"id":{"type":"number"},"username":{"type":"string"},"displayName":{"type":"string","nullable":true},"role":{"type":"string"},"plainKey":{"type":"string"}},"required":["id","username","displayName","role","plainKey"],"additionalProperties":true},"listAgentsResponse":{"type":"object","properties":{"members":{"type":"array","items":{"type":"object","properties":{"userId":{"type":"number"},"username":{"type":"string","nullable":true},"type":{"type":"string"},"role":{"type":"string"},"activeKeys":{"type":"number"}},"required":["userId","username","type","role","activeKeys"],"additionalProperties":true}}},"required":["members"],"additionalProperties":true},"deleteAgentResponse":{"type":"object","properties":{"status":{"type":"string","enum":["deleted","deactivated"]},"username":{"type":"string","nullable":true}},"required":["status","username"],"additionalProperties":true},"issueAgentKeyResponse":{"type":"object","properties":{"agentUsername":{"type":"string","nullable":true},"apiKeyName":{"type":"string"},"plainKey":{"type":"string"}},"required":["agentUsername","apiKeyName","plainKey"],"additionalProperties":true},"revokeAgentKeyResponse":{"type":"object","properties":{"agentUsername":{"type":"string","nullable":true},"keyId":{"type":"number"}},"required":["agentUsername","keyId"],"additionalProperties":true},"addNamespaceMemberResponse":{"type":"object","properties":{"userId":{"type":"number"},"username":{"type":"string","nullable":true},"role":{"type":"string"},"source":{"type":"string"}},"required":["userId","username","role","source"],"additionalProperties":true},"removeNamespaceMemberResponse":{"type":"object","properties":{"userId":{"type":"number"}},"required":["userId"],"additionalProperties":true},"updateNamespaceMemberRoleResponse":{"type":"object","properties":{"userId":{"type":"number"},"username":{"type":"string","nullable":true},"role":{"type":"string"},"source":{"type":"string"}},"required":["userId","username","role","source"],"additionalProperties":true},"listNamespaceMembersResponse":{"type":"object","properties":{"members":{"type":"array","items":{"type":"object","properties":{"userId":{"type":"number"},"username":{"type":"string","nullable":true},"type":{"type":"string"},"role":{"type":"string"},"source":{"type":"string"}},"required":["userId","username","type","role","source"],"additionalProperties":true}}},"required":["members"],"additionalProperties":true}}},"security":[]}