{"openapi":"3.1.0","info":{"title":"Workboard API","version":"1.0.0","description":"Workboard project management API by Ravefox Lab — projects, tasks, labels, and more"},"servers":[{"url":"https://work.ravefox.dev/api","description":"Workboard API Server"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key or session token (Bearer)"}},"schemas":{"InstanceStatus":{"type":"object","properties":{"hasUsers":{"type":"boolean"},"hasAdmin":{"type":"boolean"}},"required":["hasUsers","hasAdmin"]},"PublicProject":{"allOf":[{"$ref":"#/components/schemas/Board"},{"type":"object","properties":{"workspaceSlug":{"type":["string","null"]}},"required":["workspaceSlug"]}]},"BoardColumn":{"type":"object","properties":{"id":{"type":"string","description":"The column slug, same as `slug`."},"slug":{"type":"string"},"name":{"type":"string"},"icon":{"type":["string","null"]},"isFinal":{"type":"boolean"},"category":{"type":"string"},"color":{"type":["string","null"]},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/BoardTask"}}},"required":["id","slug","name","icon","isFinal","tasks"]},"BoardTask":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"number":{"type":["number","null"]},"description":{"type":["string","null"]},"status":{"type":"string"},"priority":{"type":"string","description":"One of: no-priority, low, medium, high, urgent."},"startDate":{"type":["string","null"],"format":"date-time"},"dueDate":{"type":["string","null"],"format":"date-time"},"position":{"type":["number","null"]},"createdAt":{"type":"string","format":"date-time"},"userId":{"type":["string","null"]},"assigneeName":{"type":["string","null"]},"assigneeId":{"type":["string","null"]},"assigneeImage":{"type":["string","null"]},"projectId":{"type":"string"},"cycleId":{"type":["string","null"]},"cycleName":{"type":["string","null"]},"cycleStatus":{"type":["string","null"]},"cycleStartDate":{"type":["string","null"],"format":"date-time"},"cycleEndDate":{"type":["string","null"],"format":"date-time"},"labels":{"type":"array","items":{"$ref":"#/components/schemas/TaskLabel"}},"externalLinks":{"type":"array","items":{"$ref":"#/components/schemas/TaskExternalLink"}},"subIssues":{"type":"array","items":{}},"subIssueCount":{"type":"number"},"completedSubIssueCount":{"type":"number"},"parentIssue":{}},"required":["id","title","number","status","priority","startDate","dueDate","position","createdAt","userId","assigneeName","assigneeId","assigneeImage","projectId","labels","externalLinks"]},"TaskLabel":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"color":{"type":"string"}},"required":["id","name","color"]},"TaskExternalLink":{"type":"object","properties":{"id":{"type":"string"},"taskId":{"type":"string"},"integrationId":{"type":"string"},"resourceType":{"type":"string"},"externalId":{"type":"string"},"url":{"type":"string"},"title":{"type":["string","null"]},"metadata":{"type":["object","null"],"additionalProperties":{},"description":"Provider-specific payload, already parsed from the stored JSON string."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","taskId","integrationId","resourceType","externalId","url","title","metadata"]},"Board":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"icon":{"type":["string","null"]},"logo":{"type":["string","null"]},"description":{"type":["string","null"]},"isPublic":{"type":["boolean","null"]},"workspaceId":{"type":"string"},"columns":{"type":"array","items":{"$ref":"#/components/schemas/BoardColumn"}},"archivedTasks":{"type":"array","items":{"$ref":"#/components/schemas/BoardTask"}},"plannedTasks":{"type":"array","items":{"$ref":"#/components/schemas/BoardTask"}}},"required":["id","name","slug","icon","description","isPublic","workspaceId","columns","archivedTasks","plannedTasks"]},"PublicTaskComments":{"type":"object","properties":{"comments":{"type":"array","items":{"$ref":"#/components/schemas/PublicTaskComment"}},"nextOffset":{"type":["integer","null"]}},"required":["comments","nextOffset"]},"PublicTaskComment":{"type":"object","properties":{"id":{"type":"string"},"content":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"authorName":{"type":["string","null"]}},"required":["id","content","createdAt","updatedAt","authorName"]},"Config":{"type":"object","properties":{"disableRegistration":{"type":"boolean"},"disablePasswordRegistration":{"type":"boolean"},"disableEmailOtpSignIn":{"type":"boolean"},"disableWorkspaceCreation":{"type":"boolean"},"isDemoMode":{"type":"boolean"},"hasSmtp":{"type":"boolean"},"hasGithubSignIn":{"type":"boolean"},"hasGoogleSignIn":{"type":"boolean"},"hasDiscordSignIn":{"type":"boolean"},"hasCustomOAuth":{"type":"boolean"},"hasGuestAccess":{"type":"boolean"},"disableLoginForm":{"type":"boolean"},"customOAuthAutoLogin":{"type":"boolean"},"customOAuthLogoutUrl":{"type":["string","null"]},"billingEnabled":{"type":"boolean"}},"required":["disableRegistration","disablePasswordRegistration","disableEmailOtpSignIn","disableWorkspaceCreation","isDemoMode","hasSmtp","hasGithubSignIn","hasGoogleSignIn","hasDiscordSignIn","hasCustomOAuth","hasGuestAccess","disableLoginForm","customOAuthAutoLogin","customOAuthLogoutUrl","billingEnabled"]},"McpClientRegistration":{"type":"object","properties":{"client_id":{"type":"string"},"client_id_issued_at":{"type":"number"},"redirect_uris":{"type":"array","items":{"type":"string"}},"client_name":{"type":"string"},"token_endpoint_auth_method":{"type":"string","enum":["none"]},"grant_types":{"type":"array","items":{"type":"string","enum":["authorization_code"]}},"response_types":{"type":"array","items":{"type":"string","enum":["code"]}}},"required":["client_id","client_id_issued_at","redirect_uris","token_endpoint_auth_method","grant_types","response_types"]},"OAuthError":{"type":"object","properties":{"error":{"type":"string"},"error_description":{"type":"string"}},"required":["error"]},"McpAuthorizationRequest":{"type":"object","properties":{"client_name":{"type":"string"},"redirect_uri":{"type":"string"}},"required":["client_name","redirect_uri"]},"McpAuthorizationDecision":{"type":"object","properties":{"redirect":{"type":"string","description":"Where to send the browser next: back to the client with a code on approval, or with an error on denial."}},"required":["redirect"]},"OAuthIdToken":{"type":"object","properties":{"idToken":{"type":["string","null"],"description":"The stored id_token for the user's `custom` OAuth account, or null when they have no such account."}},"required":["idToken"]},"ProjectListItem":{"allOf":[{"$ref":"#/components/schemas/Project"},{"type":"object","properties":{"statistics":{"$ref":"#/components/schemas/ProjectStatistics"},"archivedTasks":{"type":"array","items":{"$ref":"#/components/schemas/BoardTask"},"description":"Always empty."},"plannedTasks":{"type":"array","items":{"$ref":"#/components/schemas/BoardTask"},"description":"Always empty."},"columns":{"type":"array","items":{"$ref":"#/components/schemas/BoardColumn"},"description":"Always empty."}},"required":["statistics","archivedTasks","plannedTasks","columns"]}]},"ProjectStatistics":{"type":"object","properties":{"completionPercentage":{"type":"number"},"totalTasks":{"type":"number"},"dueDate":{"type":["string","null"],"format":"date-time","description":"The soonest due date among the project's open tasks."}},"required":["completionPercentage","totalTasks","dueDate"]},"Project":{"type":"object","properties":{"id":{"type":"string"},"workspaceId":{"type":"string"},"slug":{"type":"string","description":"Short prefix used in task identifiers, e.g. KAN-12."},"icon":{"type":["string","null"]},"logo":{"type":["string","null"]},"docsEnabled":{"type":"boolean"},"cyclesEnabled":{"type":"boolean"},"name":{"type":"string"},"description":{"type":["string","null"]},"links":{"type":["array","null"],"items":{"type":"object","properties":{"label":{"type":"string"},"url":{"type":"string"}},"required":["label","url"]}},"createdAt":{"type":"string","format":"date-time"},"isPublic":{"type":["boolean","null"],"description":"When true the project's board is readable without signing in, via /api/public-project/{id}."},"archivedAt":{"type":["string","null"],"format":"date-time","description":"Non-null once archived; archived projects are hidden by default."},"position":{"type":"number","description":"Sidebar order, ascending."},"lastTaskNumber":{"type":"number","description":"Highest task number issued in this project; the next task gets this plus one."}},"required":["id","workspaceId","slug","icon","docsEnabled","cyclesEnabled","name","description","createdAt","isPublic","archivedAt","position","lastTaskNumber"]},"BoardResponse":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Board"},"pagination":{"$ref":"#/components/schemas/BoardPagination"}},"required":["data","pagination"]},"BoardPagination":{"type":"object","properties":{"total":{"type":"number"},"page":{"type":"number"},"pageSize":{"type":"number"},"totalPages":{"type":"number"}},"required":["total","page","pageSize","totalPages"],"description":"When no page/limit is given, everything is returned on a single page."},"BulkTaskResult":{"type":"object","properties":{"success":{"type":"boolean"},"updatedCount":{"type":"number"}},"required":["success","updatedCount"]},"Task":{"type":"object","properties":{"id":{"type":"string"},"projectId":{"type":"string"},"position":{"type":["number","null"],"description":"Order within its column, ascending."},"number":{"type":["number","null"],"description":"Per-project counter shown as {projectSlug}-{number}."},"userId":{"type":["string","null"],"description":"The assignee, if any."},"title":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","description":"The slug of the column the task sits in."},"priority":{"type":"string","description":"One of: no-priority, low, medium, high, urgent."},"startDate":{"type":["string","null"],"format":"date-time"},"dueDate":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"customFields":{"type":"array","items":{"type":"object","properties":{"fieldId":{"type":"string"},"value":{"type":"string"}},"required":["fieldId","value"]}}},"required":["id","projectId","position","number","userId","title","description","status","priority","startDate","dueDate","createdAt"]},"MyTaskList":{"type":"array","items":{"$ref":"#/components/schemas/MyTask"}},"MyTask":{"type":"object","properties":{"id":{"type":"string"},"number":{"type":["number","null"]},"title":{"type":"string"},"status":{"type":"string"},"priority":{"type":["string","null"]},"dueDate":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"projectId":{"type":"string"},"projectName":{"type":"string"},"projectSlug":{"type":"string"},"workspaceId":{"type":"string"},"userId":{"type":["string","null"]},"assigneeId":{"type":["string","null"]},"assigneeName":{"type":["string","null"]},"assigneeImage":{"type":["string","null"]}},"required":["id","number","title","status","priority","dueDate","createdAt","updatedAt","projectId","projectName","projectSlug","workspaceId","userId","assigneeId","assigneeName","assigneeImage"]},"ResolvedTaskRef":{"type":"object","properties":{"taskId":{"type":"string"},"projectId":{"type":"string"},"workspaceId":{"type":"string"},"workspaceSlug":{"type":"string"},"identifier":{"type":"string"},"projectSlug":{"type":"string"},"taskNumber":{"type":"number"},"taskTitle":{"type":"string"}},"required":["taskId","projectId","workspaceId","workspaceSlug","identifier","projectSlug","taskNumber","taskTitle"]},"TaskWithAssignee":{"allOf":[{"$ref":"#/components/schemas/Task"},{"type":"object","properties":{"assigneeName":{"type":["string","null"]},"assigneeId":{"type":["string","null"]}},"required":["assigneeName","assigneeId"]}]},"MoveTaskResult":{"type":"object","properties":{"task":{"$ref":"#/components/schemas/Task"},"sourceProjectId":{"type":"string"},"destinationProjectId":{"type":"string"}},"required":["task","sourceProjectId","destinationProjectId"]},"BulkReorderResult":{"type":"object","properties":{"updated":{"type":"number"},"statusChangedTaskIds":{"type":"array","items":{"type":"string"}}},"required":["updated","statusChangedTaskIds"]},"TaskExport":{"type":"object","properties":{"project":{"$ref":"#/components/schemas/TaskExportProject"},"tasks":{"type":"array","items":{"$ref":"#/components/schemas/ExportedTask"}}},"required":["project","tasks"]},"TaskExportProject":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":["string","null"]},"exportedAt":{"type":"string","format":"date-time"}},"required":["name","slug","description","exportedAt"]},"ExportedTask":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"status":{"type":"string"},"priority":{"type":"string"},"dueDate":{"type":["string","null"],"format":"date-time"},"startDate":{"type":["string","null"],"format":"date-time"},"userId":{"type":["string","null"]},"labels":{"type":"array","items":{"$ref":"#/components/schemas/ExportedTaskLabel"},"description":"Label names and colors, without their ids."}},"required":["title","description","status","priority","dueDate","startDate","userId","labels"]},"ExportedTaskLabel":{"type":"object","properties":{"name":{"type":"string"},"color":{"type":"string"}},"required":["name","color"]},"TaskImportResult":{"type":"object","properties":{"results":{"$ref":"#/components/schemas/TaskImportSummary"}},"required":["results"]},"TaskImportSummary":{"type":"object","properties":{"total":{"type":"number"},"successful":{"type":"number"},"failed":{"type":"number"},"tasks":{"type":"array","items":{},"description":"Per-task outcome, each carrying a success flag."}},"required":["total","successful","failed","tasks"]},"TaskImageUpload":{"type":"object","properties":{"key":{"type":"string","description":"Object key to send back to the finalize route."},"uploadUrl":{"type":"string","description":"Presigned URL to PUT the image bytes to."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Headers that must accompany the upload request, including Content-Type."}},"required":["key","uploadUrl","headers"]},"TaskImageAsset":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string","description":"Where the stored image can be read back from."}},"required":["id","url"]},"Column":{"type":"object","properties":{"id":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string","description":"Stable identifier derived from the name; tasks store this as their status."},"position":{"type":"number","description":"Board order, ascending. Columns are always returned sorted by it."},"icon":{"type":["string","null"]},"color":{"type":["string","null"]},"isFinal":{"type":"boolean","description":"Marks the column as a done state, which stops overdue reminders for tasks in it."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","projectId","name","slug","position","icon","color","isFinal","createdAt","updatedAt"]},"WorkspaceTaskLogsStats":{"type":"object","properties":{"events":{"type":"number"},"projects":{"type":"number"},"actors":{"type":"number"},"types":{"type":"number"}},"required":["events","projects","actors","types"]},"WorkspaceTaskLogsPage":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceTaskLog"}},"hasMore":{"type":"boolean"},"nextCursor":{"type":["string","null"]}},"required":["items","hasMore","nextCursor"]},"WorkspaceTaskLog":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"content":{"type":["string","null"]},"eventData":{},"createdAt":{"type":"string","format":"date-time"},"userId":{"type":["string","null"]},"userName":{"type":["string","null"]},"userImage":{"type":["string","null"]},"externalUserName":{"type":["string","null"]},"externalUserAvatar":{"type":["string","null"]},"taskId":{"type":"string"},"taskNumber":{"type":["number","null"]},"taskTitle":{"type":"string"},"taskStatus":{"type":"string"},"projectId":{"type":"string"},"projectName":{"type":"string"},"projectSlug":{"type":"string"}},"required":["id","type","content","createdAt","userId","userName","userImage","externalUserName","externalUserAvatar","taskId","taskNumber","taskTitle","taskStatus","projectId","projectName","projectSlug"]},"Activity":{"type":"object","properties":{"id":{"type":"string"},"taskId":{"type":"string"},"type":{"type":"string","description":"One of: comment, task, create, status_changed, priority_changed, assignee_changed, unassigned, due_date_changed, title_changed, description_changed."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"userId":{"type":["string","null"]},"content":{"type":["string","null"]},"eventData":{"description":"Type-specific payload, e.g. { oldStatus, newStatus } for status_changed. Null for plain comments."},"externalUserName":{"type":["string","null"],"description":"Set when the activity was imported from another tool."},"externalUserAvatar":{"type":["string","null"]},"externalSource":{"type":["string","null"],"description":"The tool it was imported from, e.g. planka, trello, jira."},"externalUrl":{"type":["string","null"]}},"required":["id","taskId","type","createdAt","updatedAt","userId","content","externalUserName","externalUserAvatar","externalSource","externalUrl"]},"Comment":{"type":"object","properties":{"id":{"type":"string"},"taskId":{"type":"string"},"userId":{"type":"string"},"content":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"user":{"$ref":"#/components/schemas/CommentAuthor"}},"required":["id","taskId","userId","content","createdAt","updatedAt","user"]},"CommentAuthor":{"type":"object","properties":{"name":{"type":"string"},"image":{"type":["string","null"]}},"required":["name","image"]},"TimeEntryWithUser":{"allOf":[{"$ref":"#/components/schemas/TimeEntry"},{"type":"object","properties":{"userName":{"type":["string","null"]}},"required":["userName"]}]},"TimeEntry":{"type":"object","properties":{"id":{"type":"string"},"taskId":{"type":"string"},"userId":{"type":["string","null"],"description":"Null once the user who logged the time has been removed."},"description":{"type":["string","null"]},"startTime":{"type":"string","format":"date-time"},"endTime":{"type":["string","null"],"format":"date-time","description":"Null while the timer is still running."},"duration":{"type":["number","null"],"description":"Elapsed seconds, filled in once the entry has an endTime."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","taskId","userId","description","startTime","endTime","duration","createdAt","updatedAt"]},"Label":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"color":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"taskId":{"type":["string","null"]},"workspaceId":{"type":["string","null"]}},"required":["id","name","color","createdAt","updatedAt","taskId","workspaceId"]},"Notification":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"title":{"type":["string","null"]},"content":{"type":["string","null"],"description":"Free-text body. Null for generated notifications, whose text the client renders from type and eventData."},"type":{"type":"string","description":"One of: info, task_created, workspace_created, task_status_changed, task_assignee_changed, time_entry_created, due_date_reminder, task_overdue, task_mention, task_comment."},"eventData":{"description":"Type-specific payload, e.g. { taskTitle, oldStatus, newStatus, projectId, workspaceId }."},"isRead":{"type":["boolean","null"]},"resourceId":{"type":["string","null"],"description":"The id of the task or workspace the notification points at."},"resourceType":{"type":["string","null"],"description":"`task` or `workspace`."},"snoozedUntil":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","userId","title","content","type","isRead","resourceId","resourceType","createdAt","updatedAt"]},"NotificationBulkResult":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]},"NotificationPreferences":{"type":"object","properties":{"emailAddress":{"type":["string","null"]},"emailEnabled":{"type":"boolean"},"ntfyEnabled":{"type":"boolean"},"ntfyConfigured":{"type":"boolean"},"ntfyServerUrl":{"type":["string","null"]},"ntfyTopic":{"type":["string","null"]},"ntfyTokenConfigured":{"type":"boolean"},"maskedNtfyToken":{"type":["string","null"]},"gotifyEnabled":{"type":"boolean"},"gotifyConfigured":{"type":"boolean"},"gotifyServerUrl":{"type":["string","null"]},"gotifyTokenConfigured":{"type":"boolean"},"maskedGotifyToken":{"type":["string","null"]},"webhookEnabled":{"type":"boolean"},"webhookConfigured":{"type":"boolean"},"webhookUrl":{"type":["string","null"]},"webhookSecretConfigured":{"type":"boolean"},"maskedWebhookSecret":{"type":["string","null"]},"taskAssignmentEnabled":{"type":"boolean"},"taskCommentEnabled":{"type":"boolean"},"taskStatusChangeEnabled":{"type":"boolean"},"dueDateReminderEnabled":{"type":"boolean"},"dueDateReminderLeadTimeMinutes":{"type":"number","description":"How long before a due date the reminder fires, in minutes."},"workspaces":{"type":"array","items":{"$ref":"#/components/schemas/NotificationPreferenceWorkspaceRule"},"description":"Per-workspace overrides. A workspace with no rule follows the global settings."},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["emailAddress","emailEnabled","ntfyEnabled","ntfyConfigured","ntfyServerUrl","ntfyTopic","ntfyTokenConfigured","maskedNtfyToken","gotifyEnabled","gotifyConfigured","gotifyServerUrl","gotifyTokenConfigured","maskedGotifyToken","webhookEnabled","webhookConfigured","webhookUrl","webhookSecretConfigured","maskedWebhookSecret","taskAssignmentEnabled","taskCommentEnabled","taskStatusChangeEnabled","dueDateReminderEnabled","dueDateReminderLeadTimeMinutes","workspaces","createdAt","updatedAt"]},"NotificationPreferenceWorkspaceRule":{"type":"object","properties":{"id":{"type":"string"},"workspaceId":{"type":"string"},"workspaceName":{"type":"string"},"isActive":{"type":"boolean","description":"Turn all notifications for this workspace on or off."},"emailEnabled":{"type":"boolean"},"ntfyEnabled":{"type":"boolean"},"gotifyEnabled":{"type":"boolean"},"webhookEnabled":{"type":"boolean"},"projectMode":{"type":"string","enum":["all","selected"],"description":"`all` notifies for every project in the workspace; `selected` restricts it to selectedProjectIds."},"selectedProjectIds":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","workspaceId","workspaceName","isActive","emailEnabled","ntfyEnabled","gotifyEnabled","webhookEnabled","projectMode","selectedProjectIds","createdAt","updatedAt"]},"SearchResponse":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/SearchResult"}},"totalCount":{"type":"number","description":"Total matches found before the `limit` slice, so a caller can tell that more exist."},"searchQuery":{"type":"string","description":"The query that was run."}},"required":["results","totalCount","searchQuery"]},"SearchResult":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["task","project","workspace","comment","activity"]},"title":{"type":"string"},"description":{"type":"string"},"content":{"type":"string","description":"Matched body text, for comment and activity results. Activities get a rendered summary such as `changed status from Todo to In Progress`."},"projectId":{"type":"string"},"projectName":{"type":"string"},"projectSlug":{"type":"string"},"workspaceId":{"type":"string"},"workspaceName":{"type":"string"},"userId":{"type":"string"},"userName":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"relevanceScore":{"type":"number","description":"Higher is a better match. Results are sorted by score, then by createdAt descending."},"taskNumber":{"type":"number"},"priority":{"type":"string"},"status":{"type":"string"}},"required":["id","type","title","createdAt","relevanceScore"]},"GitHubAppInfo":{"type":"object","properties":{"appName":{"type":["string","null"],"description":"The configured GitHub App slug, or null when this instance has no App set up."}},"required":["appName"]},"GitHubRepositoryList":{"type":"object","properties":{"repositories":{"type":"array","items":{"$ref":"#/components/schemas/GitHubRepository"},"description":"Deduplicated across installations, most recently updated first."},"installations":{"type":"array","items":{"$ref":"#/components/schemas/GitHubInstallation"}},"total":{"type":"number"}},"required":["repositories","installations","total"]},"GitHubRepository":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"full_name":{"type":"string"},"private":{"type":"boolean"},"owner":{"$ref":"#/components/schemas/GitHubRepositoryOwner"},"description":{"type":["string","null"]},"html_url":{"type":"string"},"permissions":{"$ref":"#/components/schemas/GitHubRepositoryPermissions"},"updated_at":{"type":"string","format":"date-time"},"installation_id":{"type":"number","description":"Which App installation this repository came through."}},"required":["id","name","full_name","private","owner","description","html_url","updated_at","installation_id"]},"GitHubRepositoryOwner":{"type":"object","properties":{"login":{"type":"string"},"avatar_url":{"type":"string"},"type":{"type":"string"}},"required":["login","avatar_url","type"]},"GitHubRepositoryPermissions":{"type":"object","properties":{"admin":{"type":"boolean"},"push":{"type":"boolean"},"pull":{"type":"boolean"}},"required":["admin","push","pull"]},"GitHubInstallation":{"type":"object","properties":{"id":{"type":"number"},"account":{"$ref":"#/components/schemas/GitHubInstallationAccount"},"repositories":{"type":"array","items":{"type":"string"},"description":"Full names of the repositories under this installation. Empty when listing them failed."}},"required":["id","account","repositories"]},"GitHubInstallationAccount":{"type":["object","null"],"properties":{"login":{"type":"string"},"type":{"type":"string"}},"required":["login","type"]},"GitHubVerificationResult":{"type":"object","properties":{"isInstalled":{"type":"boolean"},"installationId":{"type":["number","null"]},"repositoryExists":{"type":["boolean","null"]},"repositoryPrivate":{"type":["boolean","null"]},"permissions":{"type":["object","null"],"additionalProperties":{"type":"string"},"description":"The permissions the installation currently grants."},"hasRequiredPermissions":{"type":"boolean"},"missingPermissions":{"type":"array","items":{"type":"string"},"description":"Permissions that must be granted before the link will work."},"message":{"type":"string","description":"A human-readable summary to show the user."},"settingsUrl":{"type":"string","description":"Where to adjust the installation, when one exists."},"installationUrl":{"type":"string","description":"Where to install the App, when it is not installed yet."}},"required":["isInstalled","installationId","repositoryExists","repositoryPrivate","permissions","hasRequiredPermissions","missingPermissions","message"]},"GitHubIntegration":{"type":["object","null"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"repositoryOwner":{"type":"string"},"repositoryName":{"type":"string"},"installationId":{"type":["number","null"],"description":"The GitHub App installation that grants access to the repository."},"branchPattern":{"type":"string","description":"Template used to name branches created for a task."},"commentTaskLinkOnGitHubIssue":{"type":"boolean","description":"When on, Kaneo comments a link back to the task on the linked GitHub issue."},"isActive":{"type":["boolean","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","projectId","repositoryOwner","repositoryName","installationId","isActive","createdAt","updatedAt"]},"CreatedGitHubIntegration":{"type":"object","properties":{"id":{"type":"string"},"projectId":{"type":"string"},"repositoryOwner":{"type":"string"},"repositoryName":{"type":"string"},"installationId":{"type":["number","null"],"description":"The GitHub App installation that grants access to the repository."},"branchPattern":{"type":"string","description":"Template used to name branches created for a task."},"commentTaskLinkOnGitHubIssue":{"type":"boolean","description":"When on, Kaneo comments a link back to the task on the linked GitHub issue."},"isActive":{"type":["boolean","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["repositoryOwner","repositoryName","installationId"]},"GitHubIntegrationNotFound":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]},"GitHubDeleteResult":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}},"required":["success","message"]},"IssueImportResult":{"type":"object","properties":{"imported":{"type":"number"},"skipped":{"type":"number","description":"Issues that already had a task, or were not importable."},"errors":{"type":"array","items":{"type":"string"}}},"required":["imported","skipped"]},"GiteaRepositoryList":{"type":"object","properties":{"repositories":{"type":"array","items":{"$ref":"#/components/schemas/GiteaRepository"}}},"required":["repositories"]},"GiteaRepository":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"full_name":{"type":"string"},"owner":{"$ref":"#/components/schemas/GiteaRepositoryOwner"},"private":{"type":"boolean"},"html_url":{"type":"string"}},"required":["id","name","full_name","owner","private","html_url"]},"GiteaRepositoryOwner":{"type":"object","properties":{"login":{"type":"string"}},"required":["login"]},"GiteaVerificationResult":{"type":"object","properties":{"isInstalled":{"type":"boolean"},"hasRequiredPermissions":{"type":"boolean"},"repositoryExists":{"type":"boolean"},"repositoryPrivate":{"type":["boolean","null"]},"missingPermissions":{"type":"array","items":{"type":"string"}},"message":{"type":"string","description":"A human-readable summary to show the user."},"failureReason":{"type":["string","null"],"enum":["not_a_gitea_instance","redirected","repository_not_found",null],"description":"Why verification failed, when it did. `redirected` usually means the base URL is behind a proxy that rewrites it."}},"required":["isInstalled","hasRequiredPermissions","repositoryExists","repositoryPrivate","missingPermissions","message","failureReason"]},"GiteaIntegration":{"type":["object","null"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"baseUrl":{"type":"string","description":"Root URL of the Gitea instance."},"repositoryOwner":{"type":"string"},"repositoryName":{"type":"string"},"maskedAccessToken":{"type":"string"},"webhookUrl":{"type":"string","description":"Where Gitea should POST events for this project."},"webhookSecret":{"type":"string","description":"Only returned to callers with workspace:manage_settings, so the value can be pasted into Gitea."},"branchPattern":{"type":"string"},"commentTaskLinkOnGiteaIssue":{"type":"boolean","description":"When on, Kaneo comments a link back to the task on the linked Gitea issue."},"isActive":{"type":["boolean","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","projectId","baseUrl","repositoryOwner","repositoryName","maskedAccessToken","isActive","createdAt","updatedAt"]},"GiteaIntegrationNotFound":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]},"GiteaDeleteResult":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}},"required":["success","message"]},"GiteaImportResult":{"type":"object","properties":{"imported":{"type":"number"},"updated":{"type":"number","description":"Existing tasks that were refreshed from their issue."},"skipped":{"type":"number"},"errors":{"type":"array","items":{"type":"string"}}},"required":["imported","updated","skipped"]},"GenericWebhookIntegration":{"type":["object","null"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"webhookConfigured":{"type":"boolean"},"maskedWebhookUrl":{"type":["string","null"]},"secretConfigured":{"type":"boolean"},"maskedSecret":{"type":["string","null"],"description":"A preview of the HMAC signing secret used to sign outgoing deliveries."},"events":{"$ref":"#/components/schemas/GenericWebhookEvents"},"dueDateReminderLeadTimeMinutes":{"type":"number","description":"How long before a due date the dueDateReminder event fires, in minutes."},"isActive":{"type":["boolean","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","projectId","webhookConfigured","maskedWebhookUrl","secretConfigured","maskedSecret","events","dueDateReminderLeadTimeMinutes","isActive","createdAt","updatedAt"]},"GenericWebhookEvents":{"allOf":[{"$ref":"#/components/schemas/IntegrationEvents"},{"type":"object","properties":{"taskDeleted":{"type":"boolean"},"taskMoved":{"type":"boolean"},"taskDueDateChanged":{"type":"boolean"},"taskAssigneeChanged":{"type":"boolean"},"taskUnassigned":{"type":"boolean"},"dueDateReminder":{"type":"boolean"}},"required":["taskDeleted","taskMoved","taskDueDateChanged","taskAssigneeChanged","taskUnassigned","dueDateReminder"]}]},"IntegrationEvents":{"type":"object","properties":{"taskCreated":{"type":"boolean"},"taskStatusChanged":{"type":"boolean"},"taskPriorityChanged":{"type":"boolean"},"taskTitleChanged":{"type":"boolean"},"taskDescriptionChanged":{"type":"boolean"},"taskCommentCreated":{"type":"boolean"}},"required":["taskCreated","taskStatusChanged","taskPriorityChanged","taskTitleChanged","taskDescriptionChanged","taskCommentCreated"]},"DiscordIntegration":{"type":["object","null"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"channelName":{"type":["string","null"]},"webhookConfigured":{"type":"boolean"},"maskedWebhookUrl":{"type":"string","description":"The webhook URL with its secret path segment masked, or an empty string when none is set."},"events":{"$ref":"#/components/schemas/IntegrationEvents"},"isActive":{"type":["boolean","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","projectId","channelName","webhookConfigured","maskedWebhookUrl","events","isActive","createdAt","updatedAt"]},"MattermostIntegration":{"type":["object","null"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"channelName":{"type":["string","null"]},"webhookConfigured":{"type":"boolean"},"maskedWebhookUrl":{"type":"string","description":"The webhook URL with its secret path segment masked, or an empty string when none is set."},"events":{"$ref":"#/components/schemas/IntegrationEvents"},"isActive":{"type":["boolean","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","projectId","channelName","webhookConfigured","maskedWebhookUrl","events","isActive","createdAt","updatedAt"]},"SlackIntegration":{"type":["object","null"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"channelName":{"type":["string","null"]},"webhookConfigured":{"type":"boolean"},"maskedWebhookUrl":{"type":"string","description":"The webhook URL with its secret path segment masked, or an empty string when none is set."},"events":{"$ref":"#/components/schemas/IntegrationEvents"},"isActive":{"type":["boolean","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","projectId","channelName","webhookConfigured","maskedWebhookUrl","events","isActive","createdAt","updatedAt"]},"TelegramIntegration":{"type":["object","null"],"properties":{"id":{"type":"string"},"projectId":{"type":"string"},"chatId":{"type":"string","description":"The Telegram chat, group, or channel messages are sent to."},"threadId":{"type":["number","null"],"description":"Forum topic id, when the target group uses topics."},"chatLabel":{"type":["string","null"],"description":"A human-readable name for the chat, shown in the UI."},"botTokenConfigured":{"type":"boolean"},"maskedBotToken":{"type":"string"},"events":{"$ref":"#/components/schemas/IntegrationEvents"},"isActive":{"type":["boolean","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","projectId","chatId","threadId","chatLabel","botTokenConfigured","maskedBotToken","events","isActive","createdAt","updatedAt"]},"TaskRelationWithTasks":{"allOf":[{"$ref":"#/components/schemas/TaskRelation"},{"type":"object","properties":{"sourceTask":{"$ref":"#/components/schemas/RelatedTask"},"targetTask":{"$ref":"#/components/schemas/RelatedTask"}},"required":["sourceTask","targetTask"]}]},"RelatedTask":{"type":["object","null"],"properties":{"id":{"type":"string"},"title":{"type":"string"},"status":{"type":"string"},"priority":{"type":["string","null"]},"number":{"type":["number","null"]},"projectId":{"type":"string"},"userId":{"type":["string","null"]},"assigneeName":{"type":["string","null"]}},"required":["id","title","status","priority","number","projectId","userId","assigneeName"]},"TaskRelation":{"type":"object","properties":{"id":{"type":"string"},"sourceTaskId":{"type":"string"},"targetTaskId":{"type":"string"},"relationType":{"type":"string","description":"How the two tasks relate: `subtask`, `blocks`, or `related`."},"createdAt":{"type":"string","format":"date-time"}},"required":["id","sourceTaskId","targetTaskId","relationType","createdAt"]},"ExternalLink":{"type":"object","properties":{"id":{"type":"string"},"taskId":{"type":"string"},"integrationId":{"type":"string"},"resourceType":{"type":"string","description":"The kind of remote resource, e.g. `issue` or `pull_request`."},"externalId":{"type":"string","description":"The provider's own identifier for the linked resource."},"url":{"type":"string"},"title":{"type":["string","null"]},"metadata":{"description":"Provider-specific payload, parsed from the stored JSON string. Null when the link has no metadata."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"integration":{"$ref":"#/components/schemas/ExternalLinkIntegration"}},"required":["id","taskId","integrationId","resourceType","externalId","url","title","createdAt","updatedAt","integration"]},"ExternalLinkIntegration":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"}},"required":["id","type"]},"WorkflowRule":{"type":"object","properties":{"id":{"type":"string"},"projectId":{"type":"string"},"integrationType":{"type":"string","description":"The integration that emits the event, e.g. `github`."},"eventType":{"type":"string","description":"The provider event that triggers the move, e.g. `pull_request.opened`."},"columnId":{"type":"string","description":"The column tasks are moved to when the event fires."},"columnName":{"type":["string","null"]},"columnSlug":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","projectId","integrationType","eventType","columnId","columnName","columnSlug","createdAt","updatedAt"]},"WorkflowRuleRow":{"type":"object","properties":{"id":{"type":"string"},"projectId":{"type":"string"},"integrationType":{"type":"string"},"eventType":{"type":"string"},"columnId":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","projectId","integrationType","eventType","columnId","createdAt","updatedAt"]},"PendingInvitation":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"workspaceId":{"type":"string"},"workspaceName":{"type":"string"},"inviterName":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"status":{"type":"string","description":"Always `pending` here; expired and accepted ones are filtered out."}},"required":["id","email","workspaceId","workspaceName","inviterName","expiresAt","createdAt","status"]},"InvitationDetails":{"type":"object","properties":{"valid":{"type":"boolean","description":"True only when the invitation can still be accepted."},"invitation":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"workspaceName":{"type":"string"},"inviterName":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"},"status":{"type":"string"},"expired":{"type":"boolean"}},"required":["id","email","workspaceName","inviterName","expiresAt","status","expired"],"description":"Omitted when the invitation does not exist, was already accepted, or was canceled -- the details are withheld rather than leaked."},"error":{"type":"string","description":"Why the invitation is unusable, when valid is false."}},"required":["valid"]},"WorkspaceMember":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"image":{"type":["string","null"]},"role":{"type":"string","description":"The member's workspace role: a built-in role (owner, admin, member, guest) or a custom role name."}},"required":["id","name","email","image","role"]},"CustomFieldDefinition":{"type":"object","properties":{"id":{"type":"string"},"projectId":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"required":{"type":"boolean"},"defaultValue":{"type":["string","null"]},"options":{},"position":{"type":"number"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","projectId","name","type","required","defaultValue","position","createdAt","updatedAt"]},"CustomFieldValue":{"type":"object","properties":{"id":{"type":"string"},"taskId":{"type":"string"},"fieldId":{"type":"string"},"value":{"type":["string","null"]},"fieldName":{"type":"string"},"fieldPosition":{"type":"number"},"fieldType":{"type":"string"},"fieldOptions":{}},"required":["id","taskId","fieldId","value","fieldName","fieldPosition","fieldType"]},"CustomFieldFilterValues":{"type":"object","properties":{"fieldId":{"type":"string"},"fieldName":{"type":"string"},"fieldType":{"type":"string"},"values":{"type":"array","items":{"type":"string"}}},"required":["fieldId","fieldName","fieldType","values"]},"ReorderCustomFieldsResponse":{},"SetCustomFieldValueResponse":{"type":"object","properties":{"id":{"type":"string"},"taskId":{"type":"string"},"fieldId":{"type":"string"},"value":{"type":["string","null"]}},"required":["id","taskId","fieldId","value"]},"UserAvatar":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string","description":"Public URL for the stored avatar, served from /api/user/avatar/{id}."},"size":{"type":"number","description":"Decoded size in bytes."}},"required":["id","url","size"]},"UserAvatarDeleted":{"type":"object","properties":{"deleted":{"type":"boolean","description":"False when the user had no uploaded avatar to remove."}},"required":["deleted"]}},"parameters":{}},"paths":{"/instance/status":{"get":{"operationId":"getInstanceStatus","tags":["Instance"],"summary":"Get instance status","description":"Public instance setup status. When hasUsers is false the next signup becomes the instance admin.","security":[],"responses":{"200":{"description":"Instance status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstanceStatus"}}}}}}},"/public-project/{id}":{"get":{"operationId":"getPublicProjectById","tags":["Project"],"summary":"Get a public project by ID","security":[],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Public project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicProject"}}}}}}},"/public-project/{workspaceSlug}/{projectSlug}":{"get":{"operationId":"getPublicProjectBySlug","tags":["Project"],"summary":"Get a public project by workspace and project key","security":[],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"workspaceSlug","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"projectSlug","in":"path"}],"responses":{"200":{"description":"Public project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicProject"}}}}}}},"/public-project/{id}/tasks/{taskId}/comments":{"get":{"operationId":"getPublicTaskComments","tags":["Project"],"summary":"Read comments on a public project task","description":"Read-only comments, newest first. Only tasks belonging to the specified public project are accessible. System activity, user IDs, emails and integration metadata are excluded. Pages contain up to 50 comments.","security":[],"parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":1},"required":true,"name":"taskId","in":"path"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":1000000,"default":0},"required":false,"name":"offset","in":"query"}],"responses":{"200":{"description":"Public task comments","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTaskComments"}}}}}}},"/auth/get-session":{"get":{"operationId":"getSession","tags":["Authentication"],"summary":"Get session","description":"Get the current authenticated session, or null when the caller is not signed in. Served by Better Auth.","security":[],"responses":{"200":{"description":"Current session details, or null when unauthenticated"}}}},"/asset/{id}":{"get":{"operationId":"getAsset","tags":["Assets"],"summary":"Download asset","description":"Download an uploaded asset. Readable without signing in only when it belongs to a public project; image types are served inline, everything else as an attachment.","security":[],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The requested asset binary stream","content":{"*/*":{"schema":{"type":"string","format":"binary"}}}},"304":{"description":"Not modified"},"403":{"description":"No access to this asset"},"404":{"description":"Asset not found"}}}},"/user/avatar/{id}":{"get":{"operationId":"getUserAvatar","tags":["User"],"summary":"Download avatar","description":"Download a user avatar by its avatar ID. Public, immutable, and cache-friendly: the id changes whenever the avatar is replaced.","security":[],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The avatar image","content":{"image/*":{"schema":{"type":"string","format":"binary"}}}},"304":{"description":"Not modified"},"404":{"description":"Avatar not found"}}}},"/config":{"get":{"operationId":"getConfig","tags":["Config"],"summary":"Get config","description":"Public instance settings: which sign-in methods, registration paths, and features are enabled.","security":[],"responses":{"200":{"description":"Application settings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Config"}}}}}}},"/auth/organization/accept-invitation":{"post":{"tags":["Organization Management"],"operationId":"acceptOrganizationInvitation","summary":"Accept Organization Invitation","description":"Accept an invitation to an organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"invitationId":{"type":"string","description":"The ID of the invitation to accept"}},"required":["invitationId"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"invitation":{"type":"object","additionalProperties":{}},"member":{"type":"object","additionalProperties":{}}}}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/add-team-member":{"post":{"tags":["Organization Management"],"operationId":"addOrganizationTeamMember","summary":"Add Organization Team Member","description":"The newly created member","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"teamId":{"type":"string","description":"The team the user should be a member of."},"userId":{"type":"string","description":"The user Id which represents the user to be added as a member."},"organizationId":{"type":"string","description":"The organization ID which the team falls under. If not provided, it will default to the user's active organization."}},"required":["teamId","userId"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier of the team member"},"userId":{"type":"string","description":"The user ID of the team member"},"teamId":{"type":"string","description":"The team ID of the team the team member is in"},"createdAt":{"type":"string","description":"Timestamp when the team member was created"}},"required":["id","userId","teamId","createdAt"]}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/cancel-invitation":{"post":{"tags":["Organization Management"],"operationId":"cancelOrganizationInvitation","summary":"Cancel Organization Invitation","description":"Cancel Organization Invitation","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"invitationId":{"type":"string","description":"The ID of the invitation to cancel"}},"required":["invitationId"]}}}},"responses":{"200":{"description":"Success"},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/check-slug":{"post":{"tags":["Organization Management"],"operationId":"checkOrganizationSlug","summary":"Check Organization Slug","description":"Check Organization Slug","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","description":"The organization slug to check. Eg: \"my-org\""}},"required":["slug"]}}}},"responses":{"200":{"description":"Success"},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/create":{"post":{"tags":["Organization Management"],"operationId":"createOrganization","summary":"Create Organization","description":"Create an organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"The name of the organization"},"slug":{"type":"string","description":"The slug of the organization"},"userId":{"type":"string","description":"The user id of the organization creator. If not provided, the current user will be used. Should only be used by admins or when called by the server. server-only. Eg: \"user-id\""},"logo":{"type":["string","null"],"description":"The logo of the organization"},"metadata":{"type":"object","additionalProperties":{},"description":"The metadata of the organization"},"keepCurrentActiveOrganization":{"type":"boolean","description":"Whether to keep the current active organization active after creating a new one. Eg: true"},"description":{"type":["string","null"]}},"required":["name","slug"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/create-role":{"post":{"tags":["Organization Management"],"operationId":"createOrganizationRole","summary":"Create Organization Role","description":"Create Organization Role","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string"},"role":{"type":"string","description":"The name of the role to create"},"permission":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"description":"The permission to assign to the role"},"additionalFields":{"type":"object","additionalProperties":{}}},"required":["role","permission"]}}}},"responses":{"200":{"description":"Success"},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/create-team":{"post":{"tags":["Organization Management"],"operationId":"createOrganizationTeam","summary":"Create Organization Team","description":"Create a new team within an organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"The name of the team. Eg: \"my-team\""},"organizationId":{"type":"string","description":"The organization ID which the team will be created in. Defaults to the active organization. Eg: \"organization-id\""}},"required":["name"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier of the created team"},"name":{"type":"string","description":"Name of the team"},"organizationId":{"type":"string","description":"ID of the organization the team belongs to"},"createdAt":{"type":"string","description":"Timestamp when the team was created"},"updatedAt":{"type":"string","description":"Timestamp when the team was last updated"}},"required":["id","name","organizationId","createdAt","updatedAt"]}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/delete":{"post":{"tags":["Organization Management"],"operationId":"deleteOrganization","summary":"Delete Organization","description":"Delete an organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","description":"The organization id to delete"}},"required":["organizationId"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/delete-role":{"post":{"tags":["Organization Management"],"operationId":"deleteOrganizationRole","summary":"Delete Organization Role","description":"Delete Organization Role","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"organizationId":{"type":"string"}}},{"anyOf":[{"type":"object","properties":{"roleName":{"type":"string","description":"The name of the role to delete"}},"required":["roleName"]},{"type":"object","properties":{"roleId":{"type":"string","description":"The id of the role to delete"}},"required":["roleId"]}]}]}}}},"responses":{"200":{"description":"Success"},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/get-active-member":{"get":{"tags":["Organization Management"],"operationId":"getOrganizationActiveMember","summary":"Get Organization Active Member","description":"Get the member details of the active organization","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"organizationId":{"type":"string"},"role":{"type":"string"}},"required":["id","userId","organizationId","role"]}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/get-active-member-role":{"get":{"tags":["Organization Management"],"operationId":"getOrganizationActiveMemberRole","summary":"Get Organization Active Member Role","description":"Get Organization Active Member Role","responses":{"200":{"description":"Success"},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/get-full-organization":{"get":{"tags":["Organization Management"],"operationId":"getOrganizationFullOrganization","summary":"Get Organization Full Organization","description":"Get the full organization","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/get-invitation":{"get":{"tags":["Organization Management"],"operationId":"getOrganizationInvitation","summary":"Get Organization Invitation","description":"Get an invitation by ID","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"query"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"role":{"type":"string"},"organizationId":{"type":"string"},"inviterId":{"type":"string"},"status":{"type":"string"},"expiresAt":{"type":"string"},"organizationName":{"type":"string"},"organizationSlug":{"type":"string"},"inviterEmail":{"type":"string"}},"required":["id","email","role","organizationId","inviterId","status","expiresAt","organizationName","organizationSlug","inviterEmail"]}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/get-role":{"get":{"tags":["Organization Management"],"operationId":"getOrganizationRole","summary":"Get Organization Role","description":"Get Organization Role","responses":{"200":{"description":"Success"},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/has-permission":{"post":{"tags":["Organization Management"],"operationId":"hasOrganizationPermission","summary":"Check Organization Permission","description":"Check if the user has permission","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"permission":{"type":"object","additionalProperties":{},"description":"The permission to check"},"permissions":{"type":"object","additionalProperties":{},"description":"The permission to check"}},"required":["permissions"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"success":{"type":"boolean"}},"required":["success"]}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/invite-member":{"post":{"tags":["Organization Management"],"operationId":"inviteOrganizationMember","summary":"Invite Organization Member","description":"Create an invitation to an organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","description":"The email address of the user to invite"},"role":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"The role(s) to assign to the user. It can be `admin`, `member`, owner. Eg: \"member\""},"organizationId":{"type":"string","description":"The organization ID to invite the user to"},"resend":{"type":"boolean","description":"Resend the invitation email, if the user is already invited. Eg: true"},"teamId":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]}},"required":["email","role"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"role":{"type":"string"},"organizationId":{"type":"string"},"inviterId":{"type":"string"},"status":{"type":"string"},"expiresAt":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","email","role","organizationId","inviterId","status","expiresAt","createdAt"]}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/leave":{"post":{"tags":["Organization Management"],"operationId":"leaveOrganization","summary":"Leave Organization","description":"Leave Organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","description":"The organization Id for the member to leave. Eg: \"organization-id\""}},"required":["organizationId"]}}}},"responses":{"200":{"description":"Success"},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/list":{"get":{"tags":["Organization Management"],"operationId":"listOrganization","summary":"List Organization","description":"List all organizations","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{}}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/list-invitations":{"get":{"tags":["Organization Management"],"operationId":"listOrganizationInvitations","summary":"List Organization Invitations","description":"List Organization Invitations","responses":{"200":{"description":"Success"},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/list-members":{"get":{"tags":["Organization Management"],"operationId":"listOrganizationMembers","summary":"List Organization Members","description":"List Organization Members","responses":{"200":{"description":"Success"},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/list-roles":{"get":{"tags":["Organization Management"],"operationId":"listOrganizationRoles","summary":"List Organization Roles","description":"List Organization Roles","responses":{"200":{"description":"Success"},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/list-team-members":{"get":{"tags":["Organization Management"],"operationId":"listOrganizationTeamMembers","summary":"List Organization Team Members","description":"List the members of the given team.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier of the team member"},"userId":{"type":"string","description":"The user ID of the team member"},"teamId":{"type":"string","description":"The team ID of the team the team member is in"},"createdAt":{"type":"string","description":"Timestamp when the team member was created"}},"required":["id","userId","teamId","createdAt"]}}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/list-teams":{"get":{"tags":["Organization Management"],"operationId":"listOrganizationTeams","summary":"List Organization Teams","description":"List all teams in an organization","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier of the team"},"name":{"type":"string","description":"Name of the team"},"organizationId":{"type":"string","description":"ID of the organization the team belongs to"},"createdAt":{"type":"string","description":"Timestamp when the team was created"},"updatedAt":{"type":"string","description":"Timestamp when the team was last updated"}},"required":["id","name","organizationId","createdAt","updatedAt"]}}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/list-user-invitations":{"get":{"tags":["Organization Management"],"operationId":"listOrganizationUserInvitations","summary":"List Organization User Invitations","description":"List all invitations a user has received","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"role":{"type":"string"},"organizationId":{"type":"string"},"organizationName":{"type":"string"},"inviterId":{"type":"string","description":"The ID of the user who created the invitation"},"teamId":{"type":["string","null"],"description":"The ID of the team associated with the invitation"},"status":{"type":"string"},"expiresAt":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","email","role","organizationId","organizationName","inviterId","status","expiresAt","createdAt"]}}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/list-user-teams":{"get":{"tags":["Organization Management"],"operationId":"listOrganizationUserTeams","summary":"List Organization User Teams","description":"List all teams that the current user is a part of.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{}}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/reject-invitation":{"post":{"tags":["Organization Management"],"operationId":"rejectOrganizationInvitation","summary":"Reject Organization Invitation","description":"Reject an invitation to an organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"invitationId":{"type":"string","description":"The ID of the invitation to reject"}},"required":["invitationId"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"invitation":{"type":"object","additionalProperties":{}},"member":{"type":["object","null"],"additionalProperties":{}}}}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/remove-member":{"post":{"tags":["Organization Management"],"operationId":"removeOrganizationMember","summary":"Remove Organization Member","description":"Remove a member from an organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"memberIdOrEmail":{"type":"string","description":"The ID or email of the member to remove"},"organizationId":{"type":"string","description":"The ID of the organization to remove the member from. If not provided, the active organization will be used. Eg: \"org-id\""}},"required":["memberIdOrEmail"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"member":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"organizationId":{"type":"string"},"role":{"type":"string"}},"required":["id","userId","organizationId","role"]}},"required":["member"]}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/remove-team":{"post":{"tags":["Organization Management"],"operationId":"removeOrganizationTeam","summary":"Remove Organization Team","description":"Remove a team from an organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"teamId":{"type":"string","description":"The team ID of the team to remove. Eg: \"team-id\""},"organizationId":{"type":"string","description":"The organization ID which the team falls under. If not provided, it will default to the user's active organization. Eg: \"organization-id\""}},"required":["teamId"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","enum":["Team removed successfully."],"description":"Confirmation message indicating successful removal"}},"required":["message"]}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/remove-team-member":{"post":{"tags":["Organization Management"],"operationId":"removeOrganizationTeamMember","summary":"Remove Organization Team Member","description":"Remove a member from a team","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"teamId":{"type":"string","description":"The team the user should be removed from."},"userId":{"type":"string","description":"The user which should be removed from the team."},"organizationId":{"type":"string","description":"The organization ID which the team falls under. If not provided, it will default to the user's active organization."}},"required":["teamId","userId"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","enum":["Team member removed successfully."],"description":"Confirmation message indicating successful removal"}},"required":["message"]}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/set-active":{"post":{"tags":["Organization Management"],"operationId":"setOrganizationActive","summary":"Set Organization Active","description":"Set the active organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":["string","null"],"description":"The organization id to set as active. It can be null to unset the active organization. Eg: \"org-id\""},"organizationSlug":{"type":"string","description":"The organization slug to set as active. It can be null to unset the active organization if organizationId is not provided. Eg: \"org-slug\""}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/set-active-team":{"post":{"tags":["Organization Management"],"operationId":"setOrganizationActiveTeam","summary":"Set Organization Active Team","description":"Set the active team for the current active organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"teamId":{"type":["string","null"],"description":"The team id to set as active. It can be null to unset the active team"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/update":{"post":{"tags":["Organization Management"],"operationId":"updateOrganization","summary":"Update Organization","description":"Update an organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"description":{"type":["string","null"]},"name":{"type":"string","description":"The name of the organization"},"slug":{"type":"string","description":"The slug of the organization"},"logo":{"type":["string","null"],"description":"The logo of the organization"},"metadata":{"type":"object","additionalProperties":{},"description":"The metadata of the organization"}}},"organizationId":{"type":"string","description":"The organization ID. Eg: \"org-id\""}},"required":["data"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/update-member-role":{"post":{"tags":["Organization Management"],"operationId":"updateOrganizationMemberRole","summary":"Update Organization Member Role","description":"Update the role of a member in an organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"The new role to be applied. This can be a string or array of strings representing the roles. Eg: [\"admin\", \"sale\"]"},"memberId":{"type":"string","description":"The member id to apply the role update to. Eg: \"member-id\""},"organizationId":{"type":"string","description":"An optional organization ID which the member is a part of to apply the role update. If not provided, you must provide session headers to get the active organization. Eg: \"organization-id\""}},"required":["role","memberId"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"member":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"organizationId":{"type":"string"},"role":{"type":"string"}},"required":["id","userId","organizationId","role"]}},"required":["member"]}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/update-role":{"post":{"tags":["Organization Management"],"operationId":"updateOrganizationRole","summary":"Update Organization Role","description":"Update Organization Role","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"type":"object","properties":{"organizationId":{"type":"string"},"data":{"type":"object","properties":{"permission":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}},"roleName":{"type":"string"}}}},"required":["data"]},{"anyOf":[{"type":"object","properties":{"roleName":{"type":"string","description":"The name of the role to update"}},"required":["roleName"]},{"type":"object","properties":{"roleId":{"type":"string","description":"The id of the role to update"}},"required":["roleId"]}]}]}}}},"responses":{"200":{"description":"Success"},"401":{"description":"Missing or invalid credentials"}}}},"/auth/organization/update-team":{"post":{"tags":["Organization Management"],"operationId":"updateOrganizationTeam","summary":"Update Organization Team","description":"Update an existing team in an organization","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"teamId":{"type":"string","description":"The ID of the team to be updated. Eg: \"team-id\""},"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"organizationId":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}},"required":["teamId","data"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier of the updated team"},"name":{"type":"string","description":"Updated name of the team"},"organizationId":{"type":"string","description":"ID of the organization the team belongs to"},"createdAt":{"type":"string","description":"Timestamp when the team was created"},"updatedAt":{"type":"string","description":"Timestamp when the team was last updated"}},"required":["id","name","organizationId","createdAt","updatedAt"]}}}},"401":{"description":"Missing or invalid credentials"}}}},"/auth/device":{"get":{"operationId":"getDeviceAuthorizationPage","tags":["Authentication"],"summary":"Device authorization page","description":"Better Auth serves this as JSON. A top-level browser navigation is redirected to the web app's device screen instead, so opening the URL by hand shows a page rather than a JSON blob.","security":[],"parameters":[{"schema":{"type":"string","description":"The device authorization user code."},"required":false,"description":"The device authorization user code.","name":"user_code","in":"query"},{"schema":{"type":"string","enum":["1"],"description":"Force a redirect to the web UI, for clients that do not send Sec-Fetch-* headers."},"required":false,"description":"Force a redirect to the web UI, for clients that do not send Sec-Fetch-* headers.","name":"ui","in":"query"}],"responses":{"200":{"description":"Device authorization payload from Better Auth"},"302":{"description":"Redirects the browser to the web app device screen"}}}},"/mcp/register":{"post":{"operationId":"registerMcpOAuthClient","tags":["MCP"],"summary":"Register MCP OAuth client","description":"Dynamically register a public OAuth client for the MCP endpoint. Public clients hold no secret, so authorization is protected by PKCE and an explicit consent step.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"redirect_uris":{"type":"array","items":{"type":"string","maxLength":2048},"minItems":1},"client_name":{"type":"string","maxLength":100},"token_endpoint_auth_method":{"type":"string","enum":["none"]},"grant_types":{"type":"array","items":{"type":"string","enum":["authorization_code","refresh_token"]}},"response_types":{"type":"array","items":{"type":"string","enum":["code"]},"minItems":1}},"required":["redirect_uris"]}}}},"responses":{"200":{"description":"Registered OAuth client","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpClientRegistration"}}}},"400":{"description":"Invalid client metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/mcp/authorize":{"get":{"operationId":"authorizeMcpOAuthClient","tags":["MCP"],"summary":"Start MCP authorization","description":"Begin an MCP OAuth authorization. Redirects the browser to the Kaneo consent page, which then approves or denies the request.","security":[],"parameters":[{"schema":{"type":"string","enum":["code"]},"required":true,"name":"response_type","in":"query"},{"schema":{"type":"string"},"required":true,"name":"client_id","in":"query"},{"schema":{"type":"string","maxLength":2048},"required":true,"name":"redirect_uri","in":"query"},{"schema":{"type":"string","minLength":1,"description":"PKCE challenge; only S256 is accepted."},"required":true,"description":"PKCE challenge; only S256 is accepted.","name":"code_challenge","in":"query"},{"schema":{"type":"string","enum":["S256"]},"required":true,"name":"code_challenge_method","in":"query"},{"schema":{"type":"string"},"required":false,"name":"state","in":"query"}],"responses":{"302":{"description":"Redirect to the Kaneo consent page"},"400":{"description":"Invalid authorization request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/mcp/authorize/request/{requestId}":{"get":{"operationId":"getMcpAuthorizationRequest","tags":["MCP"],"summary":"Get consent request","description":"Get the client name and redirect URI for a pending consent request, so the consent page can show who is asking.","security":[],"parameters":[{"schema":{"type":"string"},"required":true,"name":"requestId","in":"path"}],"responses":{"200":{"description":"Authorization request details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpAuthorizationRequest"}}}},"400":{"description":"Invalid OAuth client","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"404":{"description":"Unknown or expired authorization request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}},"post":{"operationId":"decideMcpAuthorizationRequest","tags":["MCP"],"summary":"Decide consent request","description":"Approve or deny a pending consent request and get the URL to send the browser back to.","parameters":[{"schema":{"type":"string"},"required":true,"name":"requestId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"approved":{"type":"boolean"}},"required":["approved"]}}}},"responses":{"200":{"description":"OAuth client redirect","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpAuthorizationDecision"}}}},"400":{"description":"Invalid request or OAuth client","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"403":{"description":"Untrusted request origin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"404":{"description":"Unknown or expired authorization request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}}}}},"/oauth/id-token":{"get":{"operationId":"getOAuthIdToken","tags":["Authentication"],"summary":"Get OAuth id token","description":"Get the id_token for the current user's custom OAuth account. Returns null when the user signed in another way.","responses":{"200":{"description":"The id_token if available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthIdToken"}}}},"401":{"description":"Missing or invalid credentials"}}}},"/project":{"get":{"operationId":"listProjects","tags":["Projects"],"summary":"List projects","description":"List a workspace's projects in sidebar order, each with rollup task statistics. Archived projects are excluded unless includeArchived is set.","parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceId","in":"query"},{"schema":{"type":"string","description":"Pass \"true\" to include archived projects in the list."},"required":false,"description":"Pass \"true\" to include archived projects in the list.","name":"includeArchived","in":"query"}],"responses":{"200":{"description":"List of projects","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectListItem"}}}}},"400":{"description":"Workspace ID could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"post":{"operationId":"createProject","tags":["Projects"],"summary":"Create project","description":"Create a project in a workspace. The slug becomes the prefix of its task identifiers.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"workspaceId":{"type":"string"},"icon":{"type":"string"},"slug":{"type":"string"},"logo":{"type":["string","null"]},"docsEnabled":{"type":"boolean"},"cyclesEnabled":{"type":"boolean"}},"required":["name","workspaceId","icon","slug"]}}}},"responses":{"200":{"description":"The created project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"}}}},"400":{"description":"Invalid body, or workspace ID could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing project:create permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/project/{id}":{"get":{"operationId":"getProject","tags":["Projects"],"summary":"Get project","description":"Get a single project by ID.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Project details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the project's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"put":{"operationId":"updateProject","tags":["Projects"],"summary":"Update project","description":"Replace a project's name, icon, slug, description, and visibility.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"icon":{"type":"string"},"slug":{"type":"string"},"description":{"type":"string"},"isPublic":{"type":"boolean"},"logo":{"type":["string","null"]},"links":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"url":{"type":"string"}},"required":["label","url"]}},"docsEnabled":{"type":"boolean"},"cyclesEnabled":{"type":"boolean"}},"required":["name","icon","slug","description","isPublic"]}}}},"responses":{"200":{"description":"The updated project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"}}}},"400":{"description":"Invalid body, or unknown project","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing project:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}},"delete":{"operationId":"deleteProject","tags":["Projects"],"summary":"Delete project","description":"Permanently delete a project and everything in it. Archive it instead to keep the data.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The deleted project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing project:delete permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/project/reorder":{"put":{"operationId":"reorderProjects","tags":["Projects"],"summary":"Reorder projects","description":"Set the sidebar order of a workspace's projects. The given positions express relative order only -- the workspace is renumbered to 0..n-1.","parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceId","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"projects":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"position":{"type":"integer","minimum":0}},"required":["id","position"]},"minItems":1}},"required":["projects"]}}}},"responses":{"200":{"description":"The reordered projects","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Project"}}}}},"400":{"description":"Invalid body, or workspace ID could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing project:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/project/{id}/archive":{"put":{"operationId":"archiveProject","tags":["Projects"],"summary":"Archive project","description":"Hide a project from the default list without deleting it. Reversible with unarchive.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The archived project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing project:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/project/{id}/unarchive":{"put":{"operationId":"unarchiveProject","tags":["Projects"],"summary":"Unarchive project","description":"Return an archived project to the default list.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The restored project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing project:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/project/ref/{ref}":{"get":{"operationId":"resolveProjectRef","tags":["Projects"],"summary":"Resolve project ref","description":"Resolve a project id or slug (optionally scoped by workspace slug) to its ids.","parameters":[{"schema":{"type":"string"},"required":true,"name":"ref","in":"path"},{"schema":{"type":"string"},"required":false,"name":"workspaceSlug","in":"query"}],"responses":{"200":{"description":"Resolved project","content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string"},"workspaceId":{"type":"string"},"workspaceSlug":{"type":"string"},"projectSlug":{"type":"string"}},"required":["projectId","workspaceId","workspaceSlug","projectSlug"]}}}},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Project not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/tasks/{projectId}":{"get":{"operationId":"listTasks","tags":["Tasks"],"summary":"List tasks","description":"Get a project's board: its columns, each with the tasks in it, plus the archived and planned buckets. Filter and paginate with the query parameters.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"priority","in":"query"},{"schema":{"type":"string"},"required":false,"name":"assigneeId","in":"query"},{"schema":{"type":"string","pattern":"^\\d+$"},"required":false,"name":"page","in":"query"},{"schema":{"type":"string","pattern":"^\\d+$"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","enum":["createdAt","priority","dueDate","position","title","number"]},"required":false,"name":"sortBy","in":"query"},{"schema":{"type":"string","enum":["asc","desc"]},"required":false,"name":"sortOrder","in":"query"},{"schema":{"type":"string"},"required":false,"name":"dueBefore","in":"query"},{"schema":{"type":"string"},"required":false,"name":"dueAfter","in":"query"},{"schema":{"type":"string","description":"Pass \"true\" to return only tasks that are not in a cycle."},"required":false,"description":"Pass \"true\" to return only tasks that are not in a cycle.","name":"withoutCycle","in":"query"},{"schema":{"type":"string"},"required":false,"name":"includeDescription","in":"query"},{"schema":{"type":"string"},"required":false,"name":"includeRelations","in":"query"}],"responses":{"200":{"description":"The project board","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BoardResponse"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the project's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/bulk":{"patch":{"operationId":"bulkUpdateTasks","tags":["Tasks"],"summary":"Bulk update tasks","description":"Apply one operation to many tasks at once. Every task must be in the same workspace.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"taskIds":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":200},"operation":{"type":"string","enum":["updateStatus","updatePriority","updateAssignee","delete","addLabel","removeLabel","updateDueDate"]},"value":{"type":["string","null"],"description":"The new value for the chosen operation. Unused by `delete`; null clears an assignee or due date."}},"required":["taskIds","operation"]}}}},"responses":{"200":{"description":"Bulk operation result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTaskResult"}}}},"400":{"description":"Invalid body, or the tasks span more than one workspace","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing the permission the operation needs","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"No tasks found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/{projectId}":{"post":{"operationId":"createTask","tags":["Tasks"],"summary":"Create task","description":"Add a task to a project. It is placed in the column named by `status`.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"startDate":{"type":"string"},"dueDate":{"type":"string"},"priority":{"type":"string","enum":["no-priority","low","medium","high","urgent"]},"status":{"type":"string","description":"The target column's slug."},"userId":{"type":"string","description":"Assignee, if any."},"customFields":{"type":"array","items":{"type":"object","properties":{"fieldId":{"type":"string"},"value":{"type":"string"}},"required":["fieldId","value"]}}},"required":["title","description","priority","status"]}}}},"responses":{"200":{"description":"The created task","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"400":{"description":"Invalid body, or unknown project","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:create permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/my":{"get":{"operationId":"listMyTasks","tags":["Tasks"],"summary":"List my tasks","description":"List tasks assigned to or created by the current user, optionally scoped to a workspace.","parameters":[{"schema":{"type":"string"},"required":false,"name":"workspaceId","in":"query"},{"schema":{"type":"string","enum":["assigned","created"]},"required":false,"name":"mode","in":"query"}],"responses":{"200":{"description":"Tasks for the current user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyTaskList"}}}},"401":{"description":"Missing or invalid credentials"}}}},"/task/workspace/{workspaceId}/members/{memberUserId}/tasks":{"get":{"operationId":"getWorkspaceMemberTasks","tags":["Tasks"],"summary":"List workspace member tasks","description":"List tasks for a workspace member (assigned or created). Owner only.","parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"memberUserId","in":"path"},{"schema":{"type":"string","enum":["assigned","created"]},"required":false,"name":"mode","in":"query"}],"responses":{"200":{"description":"Tasks for the workspace member","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyTaskList"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or not a workspace owner","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/ref/{ref}":{"get":{"operationId":"resolveTaskRef","tags":["Tasks"],"summary":"Resolve task ref","description":"Resolve a task by human identifier (FX-34) or task id for navigation.","parameters":[{"schema":{"type":"string"},"required":true,"name":"ref","in":"path"},{"schema":{"type":"string"},"required":false,"name":"workspaceSlug","in":"query"},{"schema":{"type":"string"},"required":false,"name":"projectSlug","in":"query"}],"responses":{"200":{"description":"Resolved task location","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolvedTaskRef"}}}},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Task not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/{id}":{"get":{"operationId":"getTask","tags":["Tasks"],"summary":"Get task","description":"Get a single task by ID, with its assignee's name resolved.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Task details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskWithAssignee"}}}},"400":{"description":"Unknown task, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the task's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"put":{"operationId":"updateTask","tags":["Tasks"],"summary":"Update task","description":"Replace every field of a task. Use the single-field routes for narrower edits.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"startDate":{"type":"string"},"dueDate":{"type":"string"},"priority":{"type":"string","enum":["no-priority","low","medium","high","urgent"]},"status":{"type":"string"},"projectId":{"type":"string"},"position":{"type":"number"},"userId":{"type":"string"}},"required":["title","description","priority","status","projectId","position"]}}}},"responses":{"200":{"description":"The updated task","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"400":{"description":"Invalid body, or unknown task","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update or task:assign permission","content":{"text/plain":{"schema":{"type":"string"}}}}}},"delete":{"operationId":"deleteTask","tags":["Tasks"],"summary":"Delete task","description":"Permanently delete a task and its comments, labels, and time entries.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The deleted task","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"400":{"description":"Unknown task, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:delete permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/move/{id}":{"put":{"operationId":"moveTask","tags":["Tasks"],"summary":"Move task","description":"Move a task to another project, optionally into a named column. Both projects must be in the same workspace.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"destinationProjectId":{"type":"string"},"destinationStatus":{"type":"string","description":"Defaults to the destination project's first column."}},"required":["destinationProjectId"]}}}},"responses":{"200":{"description":"The moved task, with both project ids","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoveTaskResult"}}}},"400":{"description":"Invalid body, or unknown task","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Task or destination project not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/reorder":{"put":{"operationId":"bulkUpdateTaskOrder","tags":["Tasks"],"summary":"Reorder tasks","description":"Batch update task status and position without touching other fields.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string"},"updates":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"position":{"type":"number"}},"required":["id","status","position"]}}},"required":["projectId","updates"]}}}},"responses":{"200":{"description":"Task order updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkReorderResult"}}}},"400":{"description":"Invalid body, or tasks do not belong to the project","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/export/{projectId}":{"get":{"operationId":"exportTasks","tags":["Tasks"],"summary":"Export tasks","description":"Export a project's tasks, with their labels, as a JSON document.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"The exported project and tasks","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskExport"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the project's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/import/{projectId}":{"post":{"operationId":"importTasks","tags":["Tasks"],"summary":"Import tasks","description":"Import tasks into a project. Each task is reported individually, so a partial import still returns 200.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tasks":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"status":{"type":"string"},"priority":{"type":"string"},"startDate":{"type":["string","null"]},"dueDate":{"type":["string","null"]},"userId":{"type":["string","null"]}},"required":["title","status"]}}},"required":["tasks"]}}}},"responses":{"200":{"description":"Per-task import outcome","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskImportResult"}}}},"400":{"description":"Invalid body, or unknown project","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:create permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/status/{id}":{"put":{"operationId":"updateTaskStatus","tags":["Tasks"],"summary":"Update task status","description":"Move a task to another column in the same project.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"}},"required":["status"]}}}},"responses":{"200":{"description":"The updated task","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"400":{"description":"Invalid body, or unknown task","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/order/{id}":{"put":{"operationId":"updateTaskOrder","tags":["Tasks"],"summary":"Update task order","description":"Update task status and position without touching other fields.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"position":{"type":"number"}},"required":["status","position"]}}}},"responses":{"200":{"description":"The updated task","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"400":{"description":"Invalid body, or unknown task","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/priority/{id}":{"put":{"operationId":"updateTaskPriority","tags":["Tasks"],"summary":"Update task priority","description":"Set a task's priority.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"priority":{"type":"string","enum":["no-priority","low","medium","high","urgent"]}},"required":["priority"]}}}},"responses":{"200":{"description":"The updated task","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"400":{"description":"Invalid priority, or unknown task","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/assignee/{id}":{"put":{"operationId":"updateTaskAssignee","tags":["Tasks"],"summary":"Update task assignee","description":"Assign a task to a workspace member, or send null to unassign it.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":["string","null"],"description":"Null unassigns."}},"required":["userId"]}}}},"responses":{"200":{"description":"The updated task","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"400":{"description":"Invalid body, or unknown task","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:assign permission","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Assignee is not a member of the workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/due-date/{id}":{"put":{"operationId":"updateTaskDueDate","tags":["Tasks"],"summary":"Update task due date","description":"Set or clear a task's due date.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dueDate":{"type":"string"}}}}}},"responses":{"200":{"description":"The updated task","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"400":{"description":"Invalid date, or unknown task","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/title/{id}":{"put":{"operationId":"updateTaskTitle","tags":["Tasks"],"summary":"Update task title","description":"Rename a task.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"}},"required":["title"]}}}},"responses":{"200":{"description":"The updated task","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"400":{"description":"Invalid body, or unknown task","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/image-upload/{id}":{"put":{"operationId":"createTaskImageUpload","tags":["Tasks"],"summary":"Create image upload URL","description":"Get a presigned URL for uploading an image used in a task description or comment. PUT the bytes to it, then call the finalize route.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"filename":{"type":"string"},"contentType":{"type":"string"},"size":{"type":"number"},"surface":{"type":"string","enum":["description","comment"],"description":"Where the image is used, which decides how it is scoped."}},"required":["filename","contentType","size","surface"]}}}},"responses":{"200":{"description":"The presigned upload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskImageUpload"}}}},"400":{"description":"Unsupported content type, or the file is too large","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Task not found","content":{"text/plain":{"schema":{"type":"string"}}}},"503":{"description":"Image uploads are not configured on this instance","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/image-upload/{id}/finalize":{"post":{"operationId":"finalizeTaskImageUpload","tags":["Tasks"],"summary":"Finalize image upload","description":"Record an uploaded image as a private asset and return the URL to reference it by.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string","description":"The key returned when the URL was issued."},"filename":{"type":"string"},"contentType":{"type":"string"},"size":{"type":"number"},"surface":{"type":"string","enum":["description","comment"],"description":"Where the image is used, which decides how it is scoped."}},"required":["key","filename","contentType","size","surface"]}}}},"responses":{"200":{"description":"The stored asset","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskImageAsset"}}}},"400":{"description":"Invalid upload, or the key does not belong to this task","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Task not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task/description/{id}":{"put":{"operationId":"updateTaskDescription","tags":["Tasks"],"summary":"Update task description","description":"Replace a task's description.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"description":{"type":"string"}},"required":["description"]}}}},"responses":{"200":{"description":"The updated task","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Task"}}}},"400":{"description":"Invalid body, or unknown task","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/column/{projectId}":{"get":{"operationId":"getColumns","tags":["Columns"],"summary":"Get columns","description":"Get a project's board columns, ordered by position.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"List of columns ordered by position","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Column"}}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the project's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"post":{"operationId":"createColumn","tags":["Columns"],"summary":"Create column","description":"Add a column to the end of a project's board. The slug is derived from the name.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"icon":{"type":"string"},"color":{"type":"string"},"isFinal":{"type":"boolean"}},"required":["name"]}}}},"responses":{"200":{"description":"The created column","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Column"}}}},"400":{"description":"Invalid body, or unknown project","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing project:update permission","content":{"text/plain":{"schema":{"type":"string"}}}},"409":{"description":"The slug is reserved, or already used in this project","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/column/reorder/{projectId}":{"put":{"operationId":"reorderColumns","tags":["Columns"],"summary":"Reorder columns","description":"Set new positions for a project's columns and return the whole board in its new order.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"columns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"position":{"type":"number"}},"required":["id","position"]},"description":"Every column keeps its new position. Columns from another project are rejected."}},"required":["columns"]}}}},"responses":{"200":{"description":"The reordered columns","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Column"}}}}},"400":{"description":"A column does not belong to this project","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing project:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/column/{id}":{"put":{"operationId":"updateColumn","tags":["Columns"],"summary":"Update column","description":"Update a column. Omitted fields are left unchanged; icon and color accept null to clear them.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"icon":{"type":["string","null"]},"color":{"type":["string","null"]},"isFinal":{"type":"boolean"}}}}}},"responses":{"200":{"description":"The updated column","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Column"}}}},"400":{"description":"Invalid body, or unknown column","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing project:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}},"delete":{"operationId":"deleteColumn","tags":["Columns"],"summary":"Delete column","description":"Delete an empty column. A column holding tasks is refused until they are moved or deleted.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The deleted column","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Column"}}}},"400":{"description":"Unknown column, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing project:update permission","content":{"text/plain":{"schema":{"type":"string"}}}},"409":{"description":"The column still contains tasks","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/activity/workspace/{workspaceId}/task-logs/stats":{"get":{"operationId":"getWorkspaceTaskLogsStats","tags":["Activity"],"summary":"Get workspace task log stats","description":"Aggregate task log statistics for a workspace (owner only, cached when Redis is configured).","parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"projectId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"query","in":"query"},{"schema":{"type":"string"},"required":false,"name":"actorUserId","in":"query"}],"responses":{"200":{"description":"Task log statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceTaskLogsStats"}}}},"400":{"description":"Workspace ID could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or not a workspace owner","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/activity/workspace/{workspaceId}/task-logs":{"get":{"operationId":"getWorkspaceTaskLogs","tags":["Activity"],"summary":"Get workspace task logs","description":"Get paginated task activity logs across workspace projects (owner only).","parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"projectId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"query","in":"query"},{"schema":{"type":"string"},"required":false,"name":"actorUserId","in":"query"},{"schema":{"type":"string","pattern":"^\\d+$"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"Paginated task activity logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceTaskLogsPage"}}}},"400":{"description":"Invalid cursor, or workspace ID could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or not a workspace owner","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/activity/{taskId}":{"get":{"operationId":"getActivities","tags":["Activity"],"summary":"Get task activity","description":"Get a task's full activity feed, newest first: comments alongside system events such as status and assignee changes.","parameters":[{"schema":{"type":"string"},"required":true,"name":"taskId","in":"path"}],"responses":{"200":{"description":"List of activities for the task","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Activity"}}}}},"400":{"description":"Unknown task, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the task's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/activity/create":{"post":{"operationId":"createActivity","tags":["Activity"],"summary":"Create activity","description":"Record a system-generated event on a task. Most events are written by the server itself; this exists for importers and integrations.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"taskId":{"type":"string"},"message":{"type":["string","null"],"description":"Free-text body. Null for events whose meaning is in eventData."},"type":{"type":"string","description":"The event kind, e.g. status_changed or assignee_changed."},"eventData":{"type":["object","null"],"additionalProperties":{},"description":"Type-specific payload stored alongside the event."}},"required":["taskId","message","type"]}}}},"responses":{"200":{"description":"The created activity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Activity"}}}},"400":{"description":"Invalid body, or unknown task","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/activity/comment":{"post":{"operationId":"createComment","tags":["Activity"],"summary":"Create comment","description":"Add a comment to a task. Equivalent to POST /comment/{taskId}, kept for the activity-feed client.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"taskId":{"type":"string"},"comment":{"type":"string"}},"required":["taskId","comment"]}}}},"responses":{"200":{"description":"The created comment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Activity"}}}},"400":{"description":"Invalid body, or unknown task","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}},"put":{"operationId":"updateComment","tags":["Activity"],"summary":"Update comment","description":"Edit a comment. Only the comment's author may do this.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"activityId":{"type":"string"},"comment":{"type":"string"}},"required":["activityId","comment"]}}}},"responses":{"200":{"description":"The updated comment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Activity"}}}},"400":{"description":"Invalid body, or unknown activity","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"Not the author, or no access to the workspace","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Comment not found","content":{"text/plain":{"schema":{"type":"string"}}}}}},"delete":{"operationId":"deleteComment","tags":["Activity"],"summary":"Delete comment","description":"Delete a comment. Only the comment's author may do this.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"activityId":{"type":"string"}},"required":["activityId"]}}}},"responses":{"200":{"description":"The deleted comment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Activity"}}}},"400":{"description":"Invalid body, or unknown activity","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"Not the author, or no access to the workspace","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Comment not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/comment/{taskId}":{"get":{"operationId":"getTaskComments","tags":["Comments"],"summary":"Get task comments","description":"Get every comment on a task, oldest first, each with its author's name and avatar.","parameters":[{"schema":{"type":"string"},"required":true,"name":"taskId","in":"path"}],"responses":{"200":{"description":"List of comments for the task","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Comment"}}}}},"400":{"description":"Unknown task, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the task's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"post":{"operationId":"createTaskComment","tags":["Comments"],"summary":"Create task comment","description":"Add a comment to a task. Mentions in the content notify the mentioned users, and the assignee is notified too. Returns the stored activity row, which carries no author object -- read the list route for that.","parameters":[{"schema":{"type":"string"},"required":true,"name":"taskId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string","minLength":1},"externalUserName":{"type":"string","maxLength":120,"description":"Attribution for an imported comment. Ignored unless externalSource is also given."},"externalSource":{"type":"string","enum":["planka","trello","jira"],"description":"The tool the comment was imported from."}},"required":["content"]}}}},"responses":{"200":{"description":"The created comment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Activity"}}}},"400":{"description":"Invalid body, or unknown task","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/comment/{id}":{"put":{"operationId":"updateTaskComment","tags":["Comments"],"summary":"Update task comment","description":"Edit a comment. Only the comment's author may do this.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string","minLength":1}},"required":["content"]}}}},"responses":{"200":{"description":"The updated comment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Activity"}}}},"400":{"description":"Invalid body, or unknown comment","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"Not the author, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Comment not found","content":{"text/plain":{"schema":{"type":"string"}}}}}},"delete":{"operationId":"deleteTaskComment","tags":["Comments"],"summary":"Delete task comment","description":"Delete a comment. Only the comment's author may do this.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The deleted comment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Activity"}}}},"400":{"description":"Unknown comment, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"Not the author, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Comment not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/time-entry/task/{taskId}":{"get":{"operationId":"getTaskTimeEntries","tags":["Time Entries"],"summary":"Get task time entries","description":"Get every time entry logged against a task.","parameters":[{"schema":{"type":"string"},"required":true,"name":"taskId","in":"path"}],"responses":{"200":{"description":"List of time entries for the task","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TimeEntryWithUser"}}}}},"400":{"description":"Unknown task, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the task's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/time-entry/{id}":{"get":{"operationId":"getTimeEntry","tags":["Time Entries"],"summary":"Get time entry","description":"Get a single time entry by ID.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Time entry details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeEntry"}}}},"400":{"description":"Unknown entry, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the entry's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"put":{"operationId":"updateTimeEntry","tags":["Time Entries"],"summary":"Update time entry","description":"Replace a time entry's start, end, and description. Setting endTime closes a running entry and fills in its duration.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"startTime":{"type":"string","format":"date-time","example":"2026-01-31T09:00:00Z"},"endTime":{"type":"string","format":"date-time","example":"2026-01-31T09:00:00Z"},"description":{"type":"string"}},"required":["startTime"]}}}},"responses":{"200":{"description":"The updated time entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeEntry"}}}},"400":{"description":"Invalid timestamps, or unknown entry","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/time-entry":{"post":{"operationId":"createTimeEntry","tags":["Time Entries"],"summary":"Create time entry","description":"Log time against a task. Omit endTime to start a running entry that can be closed later with an update.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"taskId":{"type":"string"},"startTime":{"type":"string","format":"date-time","example":"2026-01-31T09:00:00Z"},"endTime":{"type":"string","format":"date-time","example":"2026-01-31T09:00:00Z","description":"Omit to start an open-ended entry that is still running."},"description":{"type":"string"}},"required":["taskId","startTime"]}}}},"responses":{"200":{"description":"The created time entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeEntry"}}}},"400":{"description":"Invalid timestamps, or unknown task","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/label/task/{taskId}":{"get":{"operationId":"getTaskLabels","tags":["Labels"],"summary":"Get task labels","description":"Get all labels assigned to a specific task","parameters":[{"schema":{"type":"string"},"required":true,"name":"taskId","in":"path"}],"responses":{"200":{"description":"List of labels for the task","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Label"}}}}},"400":{"description":"Unknown task, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the task's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/label/workspace/{workspaceId}":{"get":{"operationId":"getWorkspaceLabels","tags":["Labels"],"summary":"Get workspace labels","description":"Get all labels for a specific workspace","parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceId","in":"path"}],"responses":{"200":{"description":"List of labels in the workspace","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Label"}}}}},"400":{"description":"Workspace ID could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/label":{"post":{"operationId":"createLabel","tags":["Labels"],"summary":"Create label","description":"Create a new label in a workspace","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"color":{"type":"string"},"workspaceId":{"type":"string"},"taskId":{"type":"string"}},"required":["name","color","workspaceId"]}}}},"responses":{"200":{"description":"Label created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Label"}}}},"400":{"description":"Invalid body, or workspace ID could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing label:create permission","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Task not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/label/{id}":{"get":{"operationId":"getLabel","tags":["Labels"],"summary":"Get label","description":"Get a specific label by ID","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Label details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Label"}}}},"400":{"description":"Unknown label, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the label's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"put":{"operationId":"updateLabel","tags":["Labels"],"summary":"Update label","description":"Update an existing label","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"color":{"type":"string"}},"required":["name","color"]}}}},"responses":{"200":{"description":"Label updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Label"}}}},"400":{"description":"Invalid body, or unknown label","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing label:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}},"delete":{"operationId":"deleteLabel","tags":["Labels"],"summary":"Delete label","description":"Delete a label by ID","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Label deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Label"}}}},"400":{"description":"Unknown label, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing label:delete permission","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"The label's task no longer exists","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/label/{id}/task":{"put":{"operationId":"attachLabelToTask","tags":["Labels"],"summary":"Attach label to task","description":"Attach an existing label to a task","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"taskId":{"type":"string"}},"required":["taskId"]}}}},"responses":{"200":{"description":"Label attached to task successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Label"}}}},"400":{"description":"Unknown label, or label and task belong to different workspaces","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing label:update permission","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Task not found","content":{"text/plain":{"schema":{"type":"string"}}}}}},"delete":{"operationId":"detachLabelFromTask","tags":["Labels"],"summary":"Detach label from task","description":"Detach a label from its current task","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Label detached from task successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Label"}}}},"400":{"description":"Unknown label, or label is not assigned to a task","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing label:update permission","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Task not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/notification":{"get":{"operationId":"listNotifications","tags":["Notifications"],"summary":"List notifications","description":"Get every notification for the current user, read and unread.","responses":{"200":{"description":"List of notifications","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Notification"}}}}},"401":{"description":"Missing or invalid credentials"}}},"post":{"operationId":"createNotification","tags":["Notifications"],"summary":"Create notification","description":"Create a notification for the current user. Most notifications are raised by the server from task and workspace events; this exists for integrations. Returns null when the user has turned off this notification category in their preferences.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":["string","null"]},"message":{"type":["string","null"],"description":"Stored as the notification's content."},"type":{"type":"string"},"eventData":{"type":["object","null"],"additionalProperties":{}},"relatedEntityId":{"type":"string","description":"Stored as resourceId: the task or workspace being pointed at."},"relatedEntityType":{"type":"string","description":"Stored as resourceType: `task` or `workspace`."}},"required":["type"]}}}},"responses":{"200":{"description":"The created notification, or null when the user has muted this notification type","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Notification"},{"type":["object","null"]}]}}}},"400":{"description":"Invalid request","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"}}}},"/notification/{id}/read":{"patch":{"operationId":"markNotificationAsRead","tags":["Notifications"],"summary":"Mark notification read","description":"Mark one notification as read. Scoped to the current user, so another user's notification is not found.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The updated notification","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Notification"}}}},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Notification not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/notification/read-all":{"patch":{"operationId":"markAllNotificationsAsRead","tags":["Notifications"],"summary":"Mark all read","description":"Mark every notification for the current user as read.","responses":{"200":{"description":"All notifications marked as read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationBulkResult"}}}},"401":{"description":"Missing or invalid credentials"}}}},"/notification/clear-all":{"delete":{"operationId":"clearAllNotifications","tags":["Notifications"],"summary":"Clear all","description":"Permanently delete every notification for the current user. This cannot be undone.","responses":{"200":{"description":"All notifications cleared","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationBulkResult"}}}},"401":{"description":"Missing or invalid credentials"}}}},"/notification/{id}":{"delete":{"operationId":"deleteNotification","tags":["Notifications"],"summary":"Delete notification","description":"Permanently delete one notification owned by the current user.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Notification deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationBulkResult"}}}},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Notification not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/notification/{id}/snooze":{"patch":{"operationId":"snoozeNotification","tags":["Notifications"],"summary":"Snooze notification","description":"Hide a notification until the given time. Pass null to unsnooze.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"snoozedUntil":{"type":["string","null"],"format":"date-time"}},"required":["snoozedUntil"]}}}},"responses":{"200":{"description":"The updated notification","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Notification"}}}},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Notification not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/notification-preferences":{"get":{"operationId":"getNotificationPreferences","tags":["Notification Preferences"],"summary":"Get notification preferences","description":"Get how the current user is notified, globally and per workspace. Configured secrets are reported as booleans plus a masked preview, never in full.","responses":{"200":{"description":"Notification preferences","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferences"}}}},"401":{"description":"Missing or invalid credentials"}}},"put":{"operationId":"updateNotificationPreferences","tags":["Notification Preferences"],"summary":"Update notification preferences","description":"Update the global delivery settings. Omitted fields are left unchanged; a secret sent as null is cleared.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"emailEnabled":{"type":"boolean"},"ntfyEnabled":{"type":"boolean"},"ntfyServerUrl":{"type":["string","null"]},"ntfyTopic":{"type":["string","null"]},"ntfyToken":{"type":["string","null"]},"gotifyEnabled":{"type":"boolean"},"gotifyServerUrl":{"type":["string","null"]},"gotifyToken":{"type":["string","null"]},"webhookEnabled":{"type":"boolean"},"webhookUrl":{"type":["string","null"]},"webhookSecret":{"type":["string","null"]},"taskAssignmentEnabled":{"type":"boolean"},"taskCommentEnabled":{"type":"boolean"},"taskStatusChangeEnabled":{"type":"boolean"},"dueDateReminderEnabled":{"type":"boolean"},"dueDateReminderLeadTimeMinutes":{"type":"integer","minimum":5,"maximum":43200,"description":"Between 5 minutes and 30 days."}}}}}},"responses":{"200":{"description":"The updated preferences","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferences"}}}},"400":{"description":"Invalid request","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"}}}},"/notification-preferences/workspaces/{workspaceId}":{"put":{"operationId":"upsertNotificationPreferenceWorkspaceRule","tags":["Notification Preferences"],"summary":"Upsert workspace rule","description":"Create or replace the notification rule for one workspace, overriding the global settings there.","parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"isActive":{"type":"boolean"},"emailEnabled":{"type":"boolean"},"ntfyEnabled":{"type":"boolean"},"gotifyEnabled":{"type":"boolean"},"webhookEnabled":{"type":"boolean"},"projectMode":{"type":"string","enum":["all","selected"]},"selectedProjectIds":{"type":"array","items":{"type":"string"},"description":"Required in practice when projectMode is `selected`."}},"required":["isActive","emailEnabled","ntfyEnabled","gotifyEnabled","webhookEnabled","projectMode"]}}}},"responses":{"200":{"description":"The updated preferences","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferences"}}}},"400":{"description":"Invalid request","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"delete":{"operationId":"deleteNotificationPreferenceWorkspaceRule","tags":["Notification Preferences"],"summary":"Delete workspace rule","description":"Remove a workspace's rule so the workspace falls back to the global settings.","parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceId","in":"path"}],"responses":{"200":{"description":"The updated preferences","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferences"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the workspace","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Workspace rule not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/search":{"get":{"operationId":"globalSearch","tags":["Search"],"summary":"Global search","description":"Search across tasks, projects, workspaces, comments, and activities in one workspace. Results are ranked by relevance and returned as a single flat list, each entry tagged with its `type`.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"q","in":"query"},{"schema":{"type":"string","enum":["all","tasks","projects","workspaces","comments","activities"],"default":"all"},"required":false,"name":"type","in":"query"},{"schema":{"type":"string","minLength":1},"required":true,"name":"workspaceId","in":"query"},{"schema":{"type":"string"},"required":false,"name":"projectId","in":"query"},{"schema":{"type":"string","default":"20"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"email"},"required":false,"name":"userEmail","in":"query"}],"responses":{"200":{"description":"Ranked search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"Invalid query, or workspace ID could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/github-integration/app-info":{"get":{"operationId":"getGitHubAppInfo","tags":["GitHub"],"summary":"Get GitHub app info","description":"Get the GitHub App this instance is configured with, so the client can build an install link.","responses":{"200":{"description":"GitHub app information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubAppInfo"}}}},"401":{"description":"Missing or invalid credentials"}}}},"/github-integration/repositories/{projectId}":{"get":{"operationId":"listGitHubRepositories","tags":["GitHub"],"summary":"List GitHub repositories","description":"List the repositories reachable through the installed GitHub App, for picking one to link.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"Repositories reachable through the installed App","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubRepositoryList"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/github-integration/verify":{"post":{"operationId":"verifyGitHubInstallation","tags":["GitHub"],"summary":"Verify GitHub installation","description":"Check that the GitHub App is installed on a repository and holds the permissions Kaneo needs. Always 200 -- problems are reported in the body so the client can guide the user.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","minLength":1},"repositoryOwner":{"type":"string","minLength":1},"repositoryName":{"type":"string","minLength":1}},"required":["projectId","repositoryOwner","repositoryName"]}}}},"responses":{"200":{"description":"Verification result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubVerificationResult"}}}},"400":{"description":"Invalid body, or unknown project","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/github-integration/project/{projectId}":{"get":{"operationId":"getGitHubIntegration","tags":["GitHub"],"summary":"Get GitHub integration","description":"Get the GitHub integration for a project, or null when none is configured.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"GitHub integration details, or null","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubIntegration"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the project's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"post":{"operationId":"createGitHubIntegration","tags":["GitHub"],"summary":"Create GitHub integration","description":"Link a project to a GitHub repository.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"repositoryOwner":{"type":"string","minLength":1},"repositoryName":{"type":"string","minLength":1}},"required":["repositoryOwner","repositoryName"]}}}},"responses":{"200":{"description":"The stored integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedGitHubIntegration"}}}},"400":{"description":"Invalid body, or unknown project","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}}}},"patch":{"operationId":"updateGitHubIntegration","tags":["GitHub"],"summary":"Update GitHub integration","description":"Update the GitHub integration. Omitted fields keep their current value.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"isActive":{"type":"boolean"},"commentTaskLinkOnGitHubIssue":{"type":"boolean"}}}}}},"responses":{"200":{"description":"The updated integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubIntegration"}}}},"400":{"description":"The resulting config failed validation","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Integration not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubIntegrationNotFound"}}}}}},"delete":{"operationId":"deleteGitHubIntegration","tags":["GitHub"],"summary":"Delete GitHub integration","description":"Unlink a project from its GitHub repository.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"The integration was removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubDeleteResult"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"GitHub integration not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/github-integration/import-issues":{"post":{"operationId":"importGitHubIssues","tags":["GitHub"],"summary":"Import GitHub issues","description":"Import the linked repository's issues as tasks. Issues that already have a task are skipped.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string"}},"required":["projectId"]}}}},"responses":{"200":{"description":"Import summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueImportResult"}}}},"400":{"description":"projectId is required","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:create permission","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Project not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/gitea-integration/repositories":{"post":{"operationId":"listGiteaRepositories","tags":["Gitea"],"summary":"List Gitea repositories","description":"List the repositories a Gitea token can reach, for picking one to link. Sent as a POST because the token travels in the body rather than the URL.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","minLength":1},"baseUrl":{"type":"string","format":"uri"},"accessToken":{"type":"string","minLength":1}},"required":["projectId","baseUrl","accessToken"]}}}},"responses":{"200":{"description":"Accessible repositories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiteaRepositoryList"}}}},"400":{"description":"Invalid body, or unknown project","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/gitea-integration/verify":{"post":{"operationId":"verifyGiteaAccess","tags":["Gitea"],"summary":"Verify Gitea access","description":"Check that the base URL is a Gitea instance and that the token can reach the repository with the permissions Kaneo needs. Always 200 -- problems are reported in the body.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string","minLength":1},"baseUrl":{"type":"string","format":"uri"},"accessToken":{"type":"string","minLength":1},"repositoryOwner":{"type":"string","minLength":1},"repositoryName":{"type":"string","minLength":1}},"required":["projectId","baseUrl","accessToken","repositoryOwner","repositoryName"]}}}},"responses":{"200":{"description":"Verification result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiteaVerificationResult"}}}},"400":{"description":"Invalid body, or unknown project","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/gitea-integration/project/{projectId}":{"get":{"operationId":"getGiteaIntegration","tags":["Gitea"],"summary":"Get Gitea integration","description":"Get the Gitea integration for a project, or null when none is configured. The webhook secret is included only for callers with workspace:manage_settings.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"Gitea integration details, or null","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiteaIntegration"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the project's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"post":{"operationId":"createGiteaIntegration","tags":["Gitea"],"summary":"Create Gitea integration","description":"Link a project to a Gitea repository, creating the webhook Gitea will post events to. Use the verify route first to confirm the token really reaches the repository.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"baseUrl":{"type":"string","minLength":1},"accessToken":{"type":"string","description":"Omit to keep the token already stored for this project."},"repositoryOwner":{"type":"string","minLength":1},"repositoryName":{"type":"string","minLength":1}},"required":["baseUrl","repositoryOwner","repositoryName"]}}}},"responses":{"200":{"description":"The stored integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiteaIntegration"}}}},"400":{"description":"Invalid body, or unknown project","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}}}},"patch":{"operationId":"updateGiteaIntegration","tags":["Gitea"],"summary":"Update Gitea integration","description":"Update the Gitea integration. Omitted fields keep their current value.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"isActive":{"type":"boolean"},"commentTaskLinkOnGiteaIssue":{"type":"boolean"}}}}}},"responses":{"200":{"description":"The updated integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiteaIntegration"}}}},"400":{"description":"The resulting config failed validation","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Integration not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiteaIntegrationNotFound"}}}}}},"delete":{"operationId":"deleteGiteaIntegration","tags":["Gitea"],"summary":"Delete Gitea integration","description":"Unlink a project from its Gitea repository.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"The integration was removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiteaDeleteResult"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Gitea integration not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/gitea-integration/import-issues":{"post":{"operationId":"importGiteaIssues","tags":["Gitea"],"summary":"Import Gitea issues","description":"Import the linked repository's issues as tasks. Issues that already have a task are refreshed rather than duplicated.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string"}},"required":["projectId"]}}}},"responses":{"200":{"description":"Import summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GiteaImportResult"}}}},"400":{"description":"projectId is required","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:create permission","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Project not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/generic-webhook-integration/project/{projectId}":{"get":{"operationId":"getGenericWebhookIntegration","tags":["Generic Webhook"],"summary":"Get webhook integration","description":"Get the outgoing webhook integration for a project, or null when none is configured.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"Webhook integration details, or null","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericWebhookIntegration"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the project's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"post":{"operationId":"createGenericWebhookIntegration","tags":["Generic Webhook"],"summary":"Create webhook integration","description":"Create or replace the outgoing webhook for a project. Kaneo POSTs the selected task events to this URL, signed with the secret when one is set.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"webhookUrl":{"type":"string","minLength":1},"secret":{"type":"string","description":"Optional HMAC secret used to sign outgoing deliveries."},"events":{"type":"object","properties":{"taskCreated":{"type":"boolean"},"taskStatusChanged":{"type":"boolean"},"taskPriorityChanged":{"type":"boolean"},"taskTitleChanged":{"type":"boolean"},"taskDescriptionChanged":{"type":"boolean"},"taskCommentCreated":{"type":"boolean"},"taskDeleted":{"type":"boolean"},"taskMoved":{"type":"boolean"},"taskDueDateChanged":{"type":"boolean"},"taskAssigneeChanged":{"type":"boolean"},"taskUnassigned":{"type":"boolean"},"dueDateReminder":{"type":"boolean"}}},"dueDateReminderLeadTimeMinutes":{"type":"integer","minimum":5,"maximum":43200,"description":"Between 5 minutes and 30 days."}},"required":["webhookUrl"]}}}},"responses":{"200":{"description":"The stored integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericWebhookIntegration"}}}},"400":{"description":"The webhook URL failed validation","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}}}},"patch":{"operationId":"updateGenericWebhookIntegration","tags":["Generic Webhook"],"summary":"Update webhook integration","description":"Update the outgoing webhook. Omitted fields keep their current value, event toggles merge into the existing set, and a null secret clears it.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"webhookUrl":{"type":"string"},"secret":{"type":["string","null"],"description":"Send null to remove the signing secret."},"isActive":{"type":"boolean"},"events":{"type":"object","properties":{"taskCreated":{"type":"boolean"},"taskStatusChanged":{"type":"boolean"},"taskPriorityChanged":{"type":"boolean"},"taskTitleChanged":{"type":"boolean"},"taskDescriptionChanged":{"type":"boolean"},"taskCommentCreated":{"type":"boolean"},"taskDeleted":{"type":"boolean"},"taskMoved":{"type":"boolean"},"taskDueDateChanged":{"type":"boolean"},"taskAssigneeChanged":{"type":"boolean"},"taskUnassigned":{"type":"boolean"},"dueDateReminder":{"type":"boolean"}}},"dueDateReminderLeadTimeMinutes":{"type":"integer","minimum":5,"maximum":43200,"description":"Between 5 minutes and 30 days."}}}}}},"responses":{"200":{"description":"The updated integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericWebhookIntegration"}}}},"400":{"description":"The resulting config failed validation","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Webhook integration not found","content":{"text/plain":{"schema":{"type":"string"}}}}}},"delete":{"operationId":"deleteGenericWebhookIntegration","tags":["Generic Webhook"],"summary":"Delete webhook integration","description":"Remove the outgoing webhook from a project.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"The integration was removed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Webhook integration not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/discord-integration/project/{projectId}":{"get":{"operationId":"getDiscordIntegration","tags":["Discord"],"summary":"Get Discord integration","description":"Get the Discord integration for a project, or null when none is configured.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"Discord integration details, or null","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscordIntegration"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the project's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"post":{"operationId":"createDiscordIntegration","tags":["Discord"],"summary":"Create Discord integration","description":"Create or replace the Discord integration for a project. The webhook URL is checked for shape only; delivery failures surface later.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"webhookUrl":{"type":"string","minLength":1},"channelName":{"type":"string"},"events":{"type":"object","properties":{"taskCreated":{"type":"boolean"},"taskStatusChanged":{"type":"boolean"},"taskPriorityChanged":{"type":"boolean"},"taskTitleChanged":{"type":"boolean"},"taskDescriptionChanged":{"type":"boolean"},"taskCommentCreated":{"type":"boolean"}}}},"required":["webhookUrl"]}}}},"responses":{"200":{"description":"The stored integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscordIntegration"}}}},"400":{"description":"The webhook URL failed validation","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}}}},"patch":{"operationId":"updateDiscordIntegration","tags":["Discord"],"summary":"Update Discord integration","description":"Update the Discord integration. Omitted fields keep their current value, and event toggles are merged into the existing set.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"webhookUrl":{"type":"string"},"channelName":{"type":["string","null"]},"isActive":{"type":"boolean"},"events":{"type":"object","properties":{"taskCreated":{"type":"boolean"},"taskStatusChanged":{"type":"boolean"},"taskPriorityChanged":{"type":"boolean"},"taskTitleChanged":{"type":"boolean"},"taskDescriptionChanged":{"type":"boolean"},"taskCommentCreated":{"type":"boolean"}}}}}}}},"responses":{"200":{"description":"The updated integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscordIntegration"}}}},"400":{"description":"The resulting config failed validation","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Discord integration not found","content":{"text/plain":{"schema":{"type":"string"}}}}}},"delete":{"operationId":"deleteDiscordIntegration","tags":["Discord"],"summary":"Delete Discord integration","description":"Remove the Discord integration from a project.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"The integration was removed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Discord integration not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/mattermost-integration/project/{projectId}":{"get":{"operationId":"getMattermostIntegration","tags":["Mattermost"],"summary":"Get Mattermost integration","description":"Get the Mattermost integration for a project, or null when none is configured.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"Mattermost integration details, or null","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MattermostIntegration"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the project's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"post":{"operationId":"createMattermostIntegration","tags":["Mattermost"],"summary":"Create Mattermost integration","description":"Create or replace the Mattermost integration for a project. The webhook URL must use HTTPS and pass destination validation; delivery failures surface later.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"webhookUrl":{"type":"string","minLength":1},"channelName":{"type":"string"},"events":{"type":"object","properties":{"taskCreated":{"type":"boolean"},"taskStatusChanged":{"type":"boolean"},"taskPriorityChanged":{"type":"boolean"},"taskTitleChanged":{"type":"boolean"},"taskDescriptionChanged":{"type":"boolean"},"taskCommentCreated":{"type":"boolean"}}}},"required":["webhookUrl"]}}}},"responses":{"200":{"description":"The stored integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MattermostIntegration"}}}},"400":{"description":"The webhook URL failed validation","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}}}},"patch":{"operationId":"updateMattermostIntegration","tags":["Mattermost"],"summary":"Update Mattermost integration","description":"Update the Mattermost integration. Omitted fields keep their current value, and event toggles are merged into the existing set.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"webhookUrl":{"type":"string"},"channelName":{"type":["string","null"]},"isActive":{"type":"boolean"},"events":{"type":"object","properties":{"taskCreated":{"type":"boolean"},"taskStatusChanged":{"type":"boolean"},"taskPriorityChanged":{"type":"boolean"},"taskTitleChanged":{"type":"boolean"},"taskDescriptionChanged":{"type":"boolean"},"taskCommentCreated":{"type":"boolean"}}}}}}}},"responses":{"200":{"description":"The updated integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MattermostIntegration"}}}},"400":{"description":"The resulting config failed validation","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Mattermost integration not found","content":{"text/plain":{"schema":{"type":"string"}}}}}},"delete":{"operationId":"deleteMattermostIntegration","tags":["Mattermost"],"summary":"Delete Mattermost integration","description":"Remove the Mattermost integration from a project.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"The integration was removed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Mattermost integration not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/slack-integration/project/{projectId}":{"get":{"operationId":"getSlackIntegration","tags":["Slack"],"summary":"Get Slack integration","description":"Get the Slack integration for a project, or null when none is configured.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"Slack integration details, or null","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackIntegration"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the project's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"post":{"operationId":"createSlackIntegration","tags":["Slack"],"summary":"Create Slack integration","description":"Create or replace the Slack integration for a project. The webhook URL is checked for shape only; delivery failures surface later.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"webhookUrl":{"type":"string","minLength":1},"channelName":{"type":"string"},"events":{"type":"object","properties":{"taskCreated":{"type":"boolean"},"taskStatusChanged":{"type":"boolean"},"taskPriorityChanged":{"type":"boolean"},"taskTitleChanged":{"type":"boolean"},"taskDescriptionChanged":{"type":"boolean"},"taskCommentCreated":{"type":"boolean"}}}},"required":["webhookUrl"]}}}},"responses":{"200":{"description":"The stored integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackIntegration"}}}},"400":{"description":"The webhook URL failed validation","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}}}},"patch":{"operationId":"updateSlackIntegration","tags":["Slack"],"summary":"Update Slack integration","description":"Update the Slack integration. Omitted fields keep their current value, and event toggles are merged into the existing set.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"webhookUrl":{"type":"string"},"channelName":{"type":["string","null"]},"isActive":{"type":"boolean"},"events":{"type":"object","properties":{"taskCreated":{"type":"boolean"},"taskStatusChanged":{"type":"boolean"},"taskPriorityChanged":{"type":"boolean"},"taskTitleChanged":{"type":"boolean"},"taskDescriptionChanged":{"type":"boolean"},"taskCommentCreated":{"type":"boolean"}}}}}}}},"responses":{"200":{"description":"The updated integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackIntegration"}}}},"400":{"description":"The resulting config failed validation","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Slack integration not found","content":{"text/plain":{"schema":{"type":"string"}}}}}},"delete":{"operationId":"deleteSlackIntegration","tags":["Slack"],"summary":"Delete Slack integration","description":"Remove the Slack integration from a project.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"The integration was removed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Slack integration not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/telegram-integration/project/{projectId}":{"get":{"operationId":"getTelegramIntegration","tags":["Telegram"],"summary":"Get Telegram integration","description":"Get the Telegram integration for a project, or null when none is configured.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"Telegram integration details, or null","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelegramIntegration"}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the project's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"post":{"operationId":"createTelegramIntegration","tags":["Telegram"],"summary":"Create Telegram integration","description":"Create or replace the Telegram integration for a project. The bot token and chat are checked for shape only, not against Telegram.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"botToken":{"type":"string","minLength":1,"description":"A Telegram bot token, in the form 123456789:AA..."},"chatId":{"type":"string","minLength":1},"threadId":{"type":"number"},"chatLabel":{"type":"string"},"events":{"type":"object","properties":{"taskCreated":{"type":"boolean"},"taskStatusChanged":{"type":"boolean"},"taskPriorityChanged":{"type":"boolean"},"taskTitleChanged":{"type":"boolean"},"taskDescriptionChanged":{"type":"boolean"},"taskCommentCreated":{"type":"boolean"}}}},"required":["botToken","chatId"]}}}},"responses":{"200":{"description":"The stored integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelegramIntegration"}}}},"400":{"description":"The bot token or chat failed validation","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}}}},"patch":{"operationId":"updateTelegramIntegration","tags":["Telegram"],"summary":"Update Telegram integration","description":"Update the Telegram integration. Omitted fields keep their current value; threadId and chatLabel accept null to clear them.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"botToken":{"type":"string"},"chatId":{"type":"string"},"threadId":{"type":["number","null"]},"chatLabel":{"type":["string","null"]},"isActive":{"type":"boolean"},"events":{"type":"object","properties":{"taskCreated":{"type":"boolean"},"taskStatusChanged":{"type":"boolean"},"taskPriorityChanged":{"type":"boolean"},"taskTitleChanged":{"type":"boolean"},"taskDescriptionChanged":{"type":"boolean"},"taskCommentCreated":{"type":"boolean"}}}}}}}},"responses":{"200":{"description":"The updated integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelegramIntegration"}}}},"400":{"description":"The resulting config failed validation","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Telegram integration not found","content":{"text/plain":{"schema":{"type":"string"}}}}}},"delete":{"operationId":"deleteTelegramIntegration","tags":["Telegram"],"summary":"Delete Telegram integration","description":"Remove the Telegram integration from a project.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"The integration was removed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing workspace:manage_settings","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Telegram integration not found","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task-relation/{taskId}":{"get":{"operationId":"getTaskRelations","tags":["Task Relations"],"summary":"Get task relations","description":"Get every relation where the task is the source or the target, each with a summary of both linked tasks. Relations pointing outside the caller's workspace are omitted.","parameters":[{"schema":{"type":"string"},"required":true,"name":"taskId","in":"path"}],"responses":{"200":{"description":"Task relations with the linked task summaries","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TaskRelationWithTasks"}}}}},"400":{"description":"Unknown task, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the task's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task-relation":{"post":{"operationId":"createTaskRelation","tags":["Task Relations"],"summary":"Create task relation","description":"Link two tasks. Authorization is scoped to the source task's workspace.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sourceTaskId":{"type":"string"},"targetTaskId":{"type":"string"},"relationType":{"type":"string","enum":["subtask","blocks","related"]}},"required":["sourceTaskId","targetTaskId","relationType"]}}}},"responses":{"200":{"description":"The created relation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskRelation"}}}},"400":{"description":"Invalid body","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Source or target task not found","content":{"text/plain":{"schema":{"type":"string"}}}},"409":{"description":"This relation already exists","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/task-relation/{id}":{"delete":{"operationId":"deleteTaskRelation","tags":["Task Relations"],"summary":"Delete task relation","description":"Remove a link between two tasks. Returns the deleted relation.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The deleted relation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskRelation"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Task relation not found, or its source task is gone","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/external-link/task/{taskId}":{"get":{"operationId":"getExternalLinksByTask","tags":["External Links"],"summary":"Get task external links","description":"Get all links from a task to resources in connected integrations, such as GitHub or Gitea issues.","parameters":[{"schema":{"type":"string"},"required":true,"name":"taskId","in":"path"}],"responses":{"200":{"description":"External links for the task","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ExternalLink"}}}}},"400":{"description":"Unknown task, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the task's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/workflow-rule/{projectId}":{"get":{"operationId":"getWorkflowRules","tags":["Workflow Rules"],"summary":"Get workflow rules","description":"Get every workflow rule for a project. A rule moves a task to a column when an integration event fires.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"List of workflow rules","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WorkflowRule"}}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the project's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}},"put":{"operationId":"upsertWorkflowRule","tags":["Workflow Rules"],"summary":"Upsert workflow rule","description":"Create a workflow rule, or update the target column of the existing rule for the same integration and event.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"integrationType":{"type":"string"},"eventType":{"type":"string"},"columnId":{"type":"string"}},"required":["integrationType","eventType","columnId"]}}}},"responses":{"200":{"description":"The created or updated rule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowRuleRow"}}}},"400":{"description":"Invalid body, or unknown project","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing project:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/workflow-rule/{id}":{"delete":{"operationId":"deleteWorkflowRule","tags":["Workflow Rules"],"summary":"Delete workflow rule","description":"Delete a workflow rule. Returns the rule that was removed.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The deleted rule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowRuleRow"}}}},"400":{"description":"Unknown rule, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing project:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/invitation/pending":{"get":{"operationId":"getUserPendingInvitations","tags":["Invitations"],"summary":"Get pending invitations","description":"Get the current user's unexpired, unaccepted invitations. Returns an empty list until the user's email is verified.","responses":{"200":{"description":"List of pending invitations","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PendingInvitation"}}}}},"401":{"description":"Missing or invalid credentials"}}}},"/invitation/{id}":{"get":{"operationId":"getInvitationDetails","tags":["Invitations"],"summary":"Get invitation details","description":"Look up an invitation by ID. Always 200 -- an unusable invitation is reported with valid: false and a reason rather than an error status.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Invitation details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationDetails"}}}},"401":{"description":"Missing or invalid credentials"}}}},"/workspace/{workspaceId}/members":{"get":{"operationId":"getWorkspaceMembers","tags":["Workspaces"],"summary":"Get workspace members","description":"Get all members of a workspace, with their role.","parameters":[{"schema":{"type":"string"},"required":true,"name":"workspaceId","in":"path"}],"responses":{"200":{"description":"List of workspace members","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceMember"}}}}},"400":{"description":"Workspace ID could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/custom-field/project/{projectId}":{"get":{"operationId":"getCustomFieldsByProject","tags":["Custom Fields"],"summary":"Get custom fields","description":"Get all custom field definitions for a project.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"List of custom field definitions","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CustomFieldDefinition"}}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the project's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/custom-field/project/{projectId}/values":{"get":{"operationId":"getCustomFieldValuesByProject","tags":["Custom Fields"],"summary":"Get project custom field values","description":"Get all custom field values for every task in a project.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"List of custom field values for the project","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CustomFieldValue"}}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the project's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/custom-field/task/{taskId}":{"get":{"operationId":"getCustomFieldValuesByTask","tags":["Custom Fields"],"summary":"Get task custom field values","description":"Get all custom field values for a task with their definitions.","parameters":[{"schema":{"type":"string"},"required":true,"name":"taskId","in":"path"}],"responses":{"200":{"description":"List of custom field values for the task","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CustomFieldValue"}}}}},"400":{"description":"Unknown task, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the task's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/custom-field/project/{projectId}/filter-values":{"get":{"operationId":"getCustomFieldFilterValues","tags":["Custom Fields"],"summary":"Get custom field filter values","description":"Get distinct values used by tasks for each custom field of a project.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"responses":{"200":{"description":"Distinct values used for each custom field","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CustomFieldFilterValues"}}}}},"400":{"description":"Unknown project, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No access to the project's workspace","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/custom-field":{"post":{"operationId":"createCustomField","tags":["Custom Fields"],"summary":"Create custom field","description":"Create a custom field definition for a project.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"projectId":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["text","number","date","dropdown","boolean"]},"required":{"type":"boolean","default":false},"defaultValue":{"type":"string"},"options":{"type":"array","items":{"type":"string"}}},"required":["projectId","name","type"]}}}},"responses":{"200":{"description":"The created custom field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldDefinition"}}}},"400":{"description":"Invalid body, or unknown project","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing project:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/custom-field/reorder/{projectId}":{"put":{"operationId":"reorderCustomFields","tags":["Custom Fields"],"summary":"Reorder custom fields","description":"Set new positions for a project's custom fields.","parameters":[{"schema":{"type":"string"},"required":true,"name":"projectId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fields":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"position":{"type":"number"}},"required":["id","position"]}}},"required":["fields"]}}}},"responses":{"200":{"description":"The reordered custom fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderCustomFieldsResponse"}}}},"400":{"description":"A custom field does not belong to this project","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing project:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/custom-field/value":{"put":{"operationId":"setCustomFieldValue","tags":["Custom Fields"],"summary":"Set custom field value","description":"Create or update a custom field value for a task.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"taskId":{"type":"string"},"fieldId":{"type":"string"},"value":{"type":"string"}},"required":["taskId","fieldId","value"]}}}},"responses":{"200":{"description":"The saved custom field value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetCustomFieldValueResponse"}}}},"400":{"description":"Invalid body, unknown task, or unknown custom field","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing task:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/custom-field/{id}":{"delete":{"operationId":"deleteCustomField","tags":["Custom Fields"],"summary":"Delete custom field","description":"Delete a custom field definition by ID.","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The deleted custom field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomFieldDefinition"}}}},"400":{"description":"Unknown custom field, or its workspace could not be determined","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"No workspace access, or missing project:update permission","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/user/avatar":{"put":{"operationId":"uploadUserAvatar","tags":["User"],"summary":"Upload avatar","description":"Store a base64 encoded avatar (PNG, JPEG, or WebP, up to 512KB) for the current user and return its public URL. Replaces any existing avatar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contentType":{"type":"string","description":"One of image/png, image/jpeg, or image/webp.","example":"image/png"},"data":{"type":"string","description":"Base64 encoded image bytes."}},"required":["contentType","data"]}}}},"responses":{"200":{"description":"Avatar stored","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserAvatar"}}}},"400":{"description":"Unsupported content type, malformed base64, or too large","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid credentials"}}},"delete":{"operationId":"deleteUserAvatar","tags":["User"],"summary":"Delete avatar","description":"Remove the uploaded avatar of the current user. Succeeds even when there was nothing to remove.","responses":{"200":{"description":"Avatar removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserAvatarDeleted"}}}},"401":{"description":"Missing or invalid credentials"}}}}},"webhooks":{}}