{
  "openapi": "3.1.0",
  "info": {
    "title": "Kaneo API",
    "version": "1.0.0",
    "description": "Kaneo Project Management API - Manage projects, tasks, labels, and more"
  },
  "servers": [
    {
      "url": "https://cloud.kaneo.app/api",
      "description": "Kaneo API Server"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "responses": {
      "ApiKeyRateLimited": {
        "description": "The API key exceeded its rate limit or usage quota. Wait the number of seconds in Retry-After before retrying. The X-RateLimit headers are sent only when the rate limit was hit.",
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying. Omitted when an exhausted usage quota never refills.",
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Limit": {
            "description": "Requests the API key may make per window.",
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Remaining": {
            "description": "Requests left in the current window.",
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Reset": {
            "description": "Unix time in seconds when the current window resets.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key or session token (Bearer)"
      }
    },
    "schemas": {
      "ApiError": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "Human-readable description of the error.",
            "example": "Task not found"
          },
          "code": {
            "type": "string",
            "description": "Stable UPPER_SNAKE_CASE code. Derived from the status unless a more specific code applies, such as VALIDATION_ERROR or MISSING_PERMISSION.",
            "example": "NOT_FOUND"
          },
          "issues": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string",
                  "description": "Dotted path to the invalid input, prefixed with the request part (body, query, params, header).",
                  "example": "body.title"
                },
                "message": {
                  "type": "string",
                  "example": "Required"
                }
              },
              "required": [
                "path",
                "message"
              ]
            },
            "description": "Every validation issue, for VALIDATION_ERROR."
          },
          "missingPermissions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Permissions the caller lacks for this route, as resource:action, for MISSING_PERMISSION and API_KEY_SCOPE.",
            "example": [
              "task:update"
            ]
          }
        },
        "required": [
          "message",
          "code"
        ]
      },
      "InstanceStatus": {
        "type": "object",
        "properties": {
          "hasUsers": {
            "type": "boolean"
          },
          "hasAdmin": {
            "type": "boolean"
          }
        },
        "required": [
          "hasUsers",
          "hasAdmin"
        ]
      },
      "PublicBoardPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Board"
          },
          {
            "type": "object",
            "properties": {
              "pagination": {
                "$ref": "#/components/schemas/BoardPagination"
              }
            },
            "required": [
              "pagination"
            ]
          }
        ]
      },
      "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"
          },
          "position": {
            "type": "number"
          },
          "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"
            ]
          },
          "descriptionDeferred": {
            "type": "boolean",
            "description": "True when the list omits a large description; load the task detail or description pages to read it. Do not replace stored text with this null summary."
          },
          "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"
          },
          "subtaskCounts": {
            "type": "object",
            "properties": {
              "completed": {
                "type": "integer",
                "minimum": 0
              },
              "total": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": [
              "completed",
              "total"
            ],
            "description": "Direct subtasks in the workspace; completed means a final column in the child project. Public boards count only children in public projects."
          },
          "labels": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TaskLabel"
            }
          },
          "externalLinks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TaskExternalLink"
            }
          }
        },
        "required": [
          "id",
          "title",
          "number",
          "description",
          "status",
          "priority",
          "startDate",
          "dueDate",
          "position",
          "createdAt",
          "userId",
          "assigneeName",
          "assigneeId",
          "assigneeImage",
          "projectId",
          "subtaskCounts",
          "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",
              "null"
            ]
          },
          "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",
          "createdAt",
          "updatedAt"
        ]
      },
      "BoardPagination": {
        "type": "object",
        "properties": {
          "total": {
            "type": "number"
          },
          "page": {
            "type": "number"
          },
          "pageSize": {
            "type": "number"
          },
          "totalPages": {
            "type": "number"
          },
          "relatedPage": {
            "type": "number"
          },
          "relatedPageSize": {
            "type": "number"
          },
          "relatedTotalPages": {
            "type": "number"
          },
          "relatedRevision": {
            "type": "string",
            "description": "Public board labels and external links revision for this task page. Restart pagination if it changes during related-page continuations."
          },
          "revision": {
            "type": "string",
            "description": "Public board content, membership and ordering revision, including related records and visible subtask progress. Restart pagination if it changes between task or related pages."
          }
        },
        "required": [
          "total",
          "page",
          "pageSize",
          "totalPages",
          "relatedPage",
          "relatedPageSize",
          "relatedTotalPages"
        ],
        "description": "Always paginated: 50 tasks by default, at most 100 per page. Continue through totalPages to retrieve all tasks. For each task page, follow relatedPage through relatedTotalPages to retrieve all labels, external links and columns (100 related rows per kind per request, plus up to 100 columns needed to represent the tasks)."
      },
      "Board": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "icon": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "descriptionDeferred": {
            "type": "boolean",
            "description": "True when a project description above 64 KiB is omitted; use project detail or public project description pages for full text."
          },
          "isPublic": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "workspaceId": {
            "type": "string"
          },
          "backgroundVersion": {
            "type": [
              "string",
              "null"
            ]
          },
          "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",
          "backgroundVersion",
          "columns",
          "archivedTasks",
          "plannedTasks"
        ]
      },
      "TaskDescriptionPage": {
        "type": "object",
        "properties": {
          "content": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "nextOffset": {
            "type": [
              "number",
              "null"
            ]
          }
        },
        "required": [
          "content",
          "version",
          "nextOffset"
        ]
      },
      "Config": {
        "type": "object",
        "properties": {
          "isCloud": {
            "type": "boolean"
          },
          "disableRegistration": {
            "type": "boolean"
          },
          "disablePasswordRegistration": {
            "type": "boolean"
          },
          "disableEmailOtpSignIn": {
            "type": "boolean"
          },
          "disableWorkspaceCreation": {
            "type": "boolean"
          },
          "isDemoMode": {
            "type": "boolean"
          },
          "hasSmtp": {
            "type": "boolean"
          },
          "hasImageUploads": {
            "type": "boolean",
            "description": "Whether S3-compatible storage is configured, so task images and board backgrounds can be uploaded."
          },
          "hasGithubSignIn": {
            "type": "boolean"
          },
          "hasGoogleSignIn": {
            "type": "boolean"
          },
          "hasDiscordSignIn": {
            "type": "boolean"
          },
          "hasCustomOAuth": {
            "type": "boolean"
          },
          "hasGuestAccess": {
            "type": "boolean"
          },
          "disableLoginForm": {
            "type": "boolean"
          },
          "customOAuthName": {
            "type": [
              "string",
              "null"
            ],
            "description": "Label for the custom OAuth provider on the sign-in page. Null means the generic SSO label."
          },
          "customOAuthAutoLogin": {
            "type": "boolean"
          },
          "customOAuthLogoutUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "billingEnabled": {
            "type": "boolean"
          }
        },
        "required": [
          "isCloud",
          "disableRegistration",
          "disablePasswordRegistration",
          "disableEmailOtpSignIn",
          "disableWorkspaceCreation",
          "isDemoMode",
          "hasSmtp",
          "hasImageUploads",
          "hasGithubSignIn",
          "hasGoogleSignIn",
          "hasDiscordSignIn",
          "hasCustomOAuth",
          "hasGuestAccess",
          "disableLoginForm",
          "customOAuthName",
          "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"
        ]
      },
      "MovedProject": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Project"
          },
          {
            "type": "object",
            "properties": {
              "unassignedTaskCount": {
                "type": "number"
              }
            },
            "required": [
              "unassignedTaskCount"
            ]
          }
        ]
      },
      "Project": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "workspaceId": {
            "type": "string"
          },
          "backgroundVersion": {
            "type": [
              "string",
              "null"
            ]
          },
          "slug": {
            "type": "string",
            "description": "Short prefix used in task identifiers, e.g. KAN-12."
          },
          "icon": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "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",
          "backgroundVersion",
          "slug",
          "icon",
          "name",
          "description",
          "createdAt",
          "isPublic",
          "archivedAt",
          "position",
          "lastTaskNumber"
        ]
      },
      "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"
        ]
      },
      "ProjectBackgroundUpload": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string"
          },
          "uploadUrl": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        },
        "required": [
          "key",
          "uploadUrl",
          "version",
          "headers"
        ]
      },
      "ProjectBackgroundFinalize": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          }
        },
        "required": [
          "url"
        ]
      },
      "CalendarFeed": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "token": {
            "type": "string"
          },
          "labelIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "timeZone": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "projectId",
          "token",
          "labelIds",
          "timeZone",
          "createdAt"
        ]
      },
      "TaskDescriptionMatches": {
        "type": "object",
        "properties": {
          "ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "ids",
          "nextCursor"
        ]
      },
      "AssignedTasks": {
        "type": "object",
        "properties": {
          "tasks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AssignedTask"
            }
          },
          "total": {
            "type": "number",
            "description": "All open tasks assigned to the caller, including any beyond the first 100 returned."
          }
        },
        "required": [
          "tasks",
          "total"
        ]
      },
      "AssignedTask": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "number": {
            "type": [
              "number",
              "null"
            ]
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "The slug of the column the task sits in."
          },
          "statusName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The column's display name. Null for tasks outside a column, such as planned ones."
          },
          "statusIcon": {
            "type": [
              "string",
              "null"
            ]
          },
          "priority": {
            "type": "string",
            "description": "One of: no-priority, low, medium, high, urgent."
          },
          "dueDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "projectName": {
            "type": "string"
          },
          "projectSlug": {
            "type": "string"
          },
          "projectIcon": {
            "type": [
              "string",
              "null"
            ]
          },
          "labels": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TaskLabel"
            }
          }
        },
        "required": [
          "id",
          "projectId",
          "number",
          "title",
          "status",
          "statusName",
          "statusIcon",
          "priority",
          "dueDate",
          "projectName",
          "projectSlug",
          "projectIcon",
          "labels"
        ]
      },
      "BoardResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Board"
          },
          "pagination": {
            "$ref": "#/components/schemas/BoardPagination"
          }
        },
        "required": [
          "data",
          "pagination"
        ]
      },
      "BulkTaskResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "updatedCount": {
            "type": "number"
          }
        },
        "required": [
          "success",
          "updatedCount"
        ]
      },
      "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"
        ]
      },
      "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"
            ]
          },
          "descriptionDeferred": {
            "type": "boolean",
            "description": "True when the list omits a large description; load the task detail or description pages to read it. Do not replace stored text with this null summary."
          },
          "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"
        ]
      },
      "TaskByTicketId": {
        "allOf": [
          {
            "$ref": "#/components/schemas/TaskWithAssignee"
          },
          {
            "type": "object",
            "properties": {
              "workspaceId": {
                "type": "string",
                "description": "The workspace that owns the task's project."
              }
            },
            "required": [
              "workspaceId"
            ]
          }
        ]
      },
      "TaskWithAssignee": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Task"
          },
          {
            "type": "object",
            "properties": {
              "workspaceId": {
                "type": "string",
                "description": "The workspace currently owning the task's project. Included in the detail view; omitted from the compact board view."
              },
              "columnId": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The referenced workflow column; null for virtual statuses and legacy tasks without a column reference."
              },
              "subtaskCounts": {
                "type": "object",
                "properties": {
                  "completed": {
                    "type": "number"
                  },
                  "total": {
                    "type": "number"
                  }
                },
                "required": [
                  "completed",
                  "total"
                ]
              },
              "parentSubtaskCounts": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "taskId": {
                      "type": "string"
                    },
                    "completed": {
                      "type": "number"
                    },
                    "total": {
                      "type": "number"
                    }
                  },
                  "required": [
                    "taskId",
                    "completed",
                    "total"
                  ]
                }
              },
              "assigneeName": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "assigneeId": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "columnId",
              "assigneeName",
              "assigneeId"
            ]
          }
        ]
      },
      "MoveTaskResult": {
        "type": "object",
        "properties": {
          "task": {
            "$ref": "#/components/schemas/Task"
          },
          "sourceProjectId": {
            "type": "string"
          },
          "destinationProjectId": {
            "type": "string"
          }
        },
        "required": [
          "task",
          "sourceProjectId",
          "destinationProjectId"
        ]
      },
      "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"
        ]
      },
      "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"
        ]
      },
      "WorkspaceActivity": {
        "type": "object",
        "properties": {
          "id": {
            "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"
          },
          "eventData": {
            "description": "Type-specific payload. For status_changed, oldStatus/newStatus are slugs and oldStatusName/newStatusName carry current configured column names when available."
          },
          "excerpt": {
            "type": [
              "string",
              "null"
            ],
            "description": "Plain-text preview of the stored content, at most 240 characters: the comment body, or the description older system events carry instead of eventData."
          },
          "userId": {
            "type": [
              "string",
              "null"
            ]
          },
          "userName": {
            "type": [
              "string",
              "null"
            ]
          },
          "userImage": {
            "type": [
              "string",
              "null"
            ]
          },
          "externalUserName": {
            "type": [
              "string",
              "null"
            ]
          },
          "externalUserAvatar": {
            "type": [
              "string",
              "null"
            ]
          },
          "taskId": {
            "type": "string"
          },
          "taskTitle": {
            "type": "string"
          },
          "taskNumber": {
            "type": [
              "number",
              "null"
            ]
          },
          "projectId": {
            "type": "string"
          },
          "projectSlug": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "createdAt",
          "excerpt",
          "userId",
          "userName",
          "userImage",
          "externalUserName",
          "externalUserAvatar",
          "taskId",
          "taskTitle",
          "taskNumber",
          "projectId",
          "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: planka, trello, jira, plane, linear, kaneo, or a connected forge such as github."
          },
          "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"
          },
          "deletionStartedAt": {
            "type": "string",
            "format": "date-time"
          },
          "taskId": {
            "type": [
              "string",
              "null"
            ]
          },
          "workspaceId": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "color",
          "createdAt",
          "updatedAt",
          "taskId",
          "workspaceId"
        ]
      },
      "PendingLabelDeletion": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Label"
          },
          {
            "type": "object",
            "properties": {
              "pendingDeletion": {
                "type": "boolean",
                "enum": [
                  true
                ]
              }
            },
            "required": [
              "pendingDeletion"
            ]
          }
        ]
      },
      "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`."
          },
          "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"
        ]
      },
      "IntegrationSyncPreview": {
        "type": "object",
        "properties": {
          "isActive": {
            "type": "boolean"
          },
          "rules": {
            "type": "object",
            "properties": {
              "outgoing": {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "mode": {
                        "type": "string",
                        "enum": [
                          "all"
                        ]
                      }
                    },
                    "required": [
                      "mode"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "mode": {
                        "type": "string",
                        "enum": [
                          "labels"
                        ]
                      },
                      "match": {
                        "type": "string",
                        "enum": [
                          "any",
                          "all"
                        ]
                      },
                      "labels": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 128
                        },
                        "minItems": 1,
                        "maxItems": 50
                      }
                    },
                    "required": [
                      "mode",
                      "match",
                      "labels"
                    ]
                  }
                ],
                "description": "Kaneo workspace label IDs controlling task sync. Missing labels pause sync."
              },
              "incoming": {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "mode": {
                        "type": "string",
                        "enum": [
                          "all"
                        ]
                      }
                    },
                    "required": [
                      "mode"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "mode": {
                        "type": "string",
                        "enum": [
                          "labels"
                        ]
                      },
                      "match": {
                        "type": "string",
                        "enum": [
                          "any",
                          "all"
                        ]
                      },
                      "labels": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 128
                        },
                        "minItems": 1,
                        "maxItems": 50
                      }
                    },
                    "required": [
                      "mode",
                      "match",
                      "labels"
                    ]
                  }
                ],
                "description": "Exact repository label names controlling which issues can be imported."
              }
            },
            "required": [
              "outgoing",
              "incoming"
            ]
          },
          "labels": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "color": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "name",
                "color"
              ]
            }
          },
          "missingLabels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "total": {
            "type": "number"
          },
          "matching": {
            "type": "number"
          },
          "willCreate": {
            "type": "number"
          },
          "willPause": {
            "type": "number"
          },
          "needsReview": {
            "type": "number"
          },
          "paused": {
            "type": "number"
          },
          "matchingTasks": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "number": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "title": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "number",
                "title"
              ]
            }
          },
          "pausedNextCursor": {
            "type": [
              "string",
              "null"
            ]
          },
          "pausedTasks": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "number": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "title": {
                  "type": "string"
                },
                "linkId": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "eligible": {
                  "type": "boolean"
                }
              },
              "required": [
                "id",
                "number",
                "title",
                "linkId",
                "url",
                "eligible"
              ]
            }
          },
          "previewToken": {
            "type": "string"
          }
        },
        "required": [
          "isActive",
          "rules",
          "labels",
          "missingLabels",
          "total",
          "matching",
          "willCreate",
          "willPause",
          "needsReview",
          "paused",
          "matchingTasks",
          "pausedNextCursor",
          "pausedTasks",
          "previewToken"
        ]
      },
      "IntegrationSyncResumePreview": {
        "type": "object",
        "properties": {
          "task": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "number": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "title": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "number",
              "title"
            ]
          },
          "local": {
            "type": "object",
            "properties": {
              "title": {
                "type": "string"
              },
              "description": {
                "type": "string"
              },
              "state": {
                "type": "string",
                "enum": [
                  "open",
                  "closed"
                ]
              }
            },
            "required": [
              "title",
              "description",
              "state"
            ]
          },
          "remote": {
            "type": "object",
            "properties": {
              "title": {
                "type": "string"
              },
              "description": {
                "type": "string"
              },
              "state": {
                "type": "string",
                "enum": [
                  "open",
                  "closed"
                ]
              }
            },
            "required": [
              "title",
              "description",
              "state"
            ]
          },
          "token": {
            "type": "string"
          }
        },
        "required": [
          "task",
          "local",
          "remote",
          "token"
        ]
      },
      "GitHubAppInfo": {
        "type": "object",
        "properties": {
          "accountConnected": {
            "type": "boolean"
          },
          "accountLinkingAvailable": {
            "type": "boolean"
          },
          "appName": {
            "type": [
              "string",
              "null"
            ],
            "description": "The configured GitHub App slug, or null when this instance has no App set up."
          }
        },
        "required": [
          "accountConnected",
          "accountLinkingAvailable",
          "appName"
        ]
      },
      "GitHubRepositoryList": {
        "type": "object",
        "properties": {
          "repositories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GitHubRepository"
            },
            "description": "Repositories the caller administers, deduplicated within the response."
          },
          "installations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GitHubInstallation"
            }
          },
          "total": {
            "type": "number"
          },
          "nextPage": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "installationPage": {
                "type": "number"
              },
              "repositoryPage": {
                "type": "number"
              }
            },
            "required": [
              "installationPage",
              "repositoryPage"
            ],
            "description": "Where to continue listing, or null when every installation has been read."
          }
        },
        "required": [
          "repositories",
          "installations",
          "total",
          "nextPage"
        ]
      },
      "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."
          },
          "requiresVerification": {
            "type": "boolean"
          },
          "importProgress": {
            "$ref": "#/components/schemas/IssueImportResult"
          },
          "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",
          "requiresVerification",
          "isActive",
          "createdAt",
          "updatedAt"
        ]
      },
      "IssueImportResult": {
        "type": "object",
        "properties": {
          "runId": {
            "type": "string"
          },
          "pending": {
            "type": "boolean"
          },
          "imported": {
            "type": "number"
          },
          "updated": {
            "type": "number"
          },
          "skipped": {
            "type": "number",
            "description": "Issues whose linked task or source disappeared or belongs to another project."
          }
        },
        "required": [
          "runId",
          "pending",
          "imported",
          "updated",
          "skipped"
        ]
      },
      "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."
          },
          "requiresVerification": {
            "type": "boolean"
          },
          "importProgress": {
            "$ref": "#/components/schemas/IssueImportResult"
          },
          "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",
          "requiresVerification"
        ]
      },
      "GitHubDeleteResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "success",
          "message"
        ]
      },
      "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"
        ]
      },
      "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"
        ]
      },
      "GitlabProjectList": {
        "type": "object",
        "properties": {
          "projects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GitlabProject"
            }
          }
        },
        "required": [
          "projects"
        ]
      },
      "GitlabProject": {
        "type": "object",
        "properties": {
          "id": {
            "type": "number"
          },
          "name": {
            "type": "string"
          },
          "path_with_namespace": {
            "type": "string"
          },
          "name_with_namespace": {
            "type": "string"
          },
          "visibility": {
            "type": "string"
          },
          "web_url": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "path_with_namespace",
          "name_with_namespace",
          "visibility",
          "web_url"
        ]
      },
      "GitlabVerificationResult": {
        "type": "object",
        "properties": {
          "isInstalled": {
            "type": "boolean",
            "description": "The base URL answered as a GitLab instance for this token."
          },
          "hasRequiredPermissions": {
            "type": "boolean"
          },
          "projectExists": {
            "type": "boolean"
          },
          "projectVisibility": {
            "type": [
              "string",
              "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_gitlab_instance",
              "redirected",
              "project_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",
          "projectExists",
          "projectVisibility",
          "missingPermissions",
          "message",
          "failureReason"
        ]
      },
      "GitlabIntegration": {
        "type": [
          "object",
          "null"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "baseUrl": {
            "type": "string",
            "description": "Root URL of the GitLab instance."
          },
          "projectPath": {
            "type": "string",
            "description": "Full path of the linked project, nested groups included."
          },
          "tokenType": {
            "type": "string",
            "enum": [
              "private",
              "bearer"
            ]
          },
          "maskedAccessToken": {
            "type": "string",
            "description": "First and last characters of the stored token, only returned to callers with workspace:manage_settings."
          },
          "webhookUrl": {
            "type": "string",
            "description": "Where GitLab 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 GitLab."
          },
          "branchPattern": {
            "type": "string"
          },
          "commentTaskLinkOnGitlabIssue": {
            "type": "boolean",
            "description": "When on, Kaneo comments a link back to the task on each issue opened in GitLab. Issues Kaneo creates from tasks are not commented on."
          },
          "isActive": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "projectId",
          "baseUrl",
          "projectPath",
          "tokenType",
          "maskedAccessToken",
          "isActive",
          "createdAt",
          "updatedAt"
        ]
      },
      "GitlabDeleteResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "success",
          "message"
        ]
      },
      "GitlabImportResult": {
        "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"
          },
          "isCompleted": {
            "type": "boolean",
            "description": "Whether the task is in a final column of its own project."
          },
          "priority": {
            "type": [
              "string",
              "null"
            ]
          },
          "number": {
            "type": [
              "number",
              "null"
            ]
          },
          "projectId": {
            "type": "string"
          },
          "userId": {
            "type": [
              "string",
              "null"
            ]
          },
          "assigneeName": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "status",
          "isCompleted",
          "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"
        ]
      },
      "CreatedExternalLink": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "taskId": {
            "type": "string"
          },
          "integrationId": {
            "type": [
              "string",
              "null"
            ]
          },
          "resourceType": {
            "type": "string",
            "description": "The resource kind: `url` for a manual link, or an integration resource such as `issue` or `pull_request`."
          },
          "externalId": {
            "type": "string",
            "description": "The provider's resource identifier, or the URL for a manual link."
          },
          "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"
          }
        },
        "required": [
          "id",
          "taskId",
          "integrationId",
          "resourceType",
          "externalId",
          "url",
          "title",
          "createdAt",
          "updatedAt"
        ]
      },
      "DeletedExternalLink": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          }
        },
        "required": [
          "id"
        ]
      },
      "ExternalLink": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "taskId": {
            "type": "string"
          },
          "integrationId": {
            "type": [
              "string",
              "null"
            ]
          },
          "resourceType": {
            "type": "string",
            "description": "The resource kind: `url` for a manual link, or an integration resource such as `issue` or `pull_request`."
          },
          "externalId": {
            "type": "string",
            "description": "The provider's resource identifier, or the URL for a manual link."
          },
          "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",
          "null"
        ],
        "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"
        ]
      },
      "Workspace": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "logo": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "role": {
            "type": [
              "string",
              "null"
            ],
            "description": "The caller's workspace role: a built-in role (owner, admin, member, viewer) or the name of a custom role defined in the workspace. Several roles are comma-separated, for example owner,viewer. Null when an instance admin views a workspace they are not a member of."
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "logo",
          "description",
          "createdAt",
          "role"
        ]
      },
      "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, viewer) or the name of a custom role defined in the workspace. Several roles are comma-separated, for example owner,viewer."
          }
        },
        "required": [
          "id",
          "name",
          "email",
          "image",
          "role"
        ]
      },
      "MemberProjectAccess": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string"
          },
          "projectAccess": {
            "type": "string",
            "enum": [
              "all",
              "selected"
            ]
          },
          "projectIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "userId",
          "projectAccess",
          "projectIds"
        ]
      },
      "WorkspaceCapabilities": {
        "type": "object",
        "properties": {
          "manageProjects": {
            "type": "boolean"
          },
          "createProjects": {
            "type": "boolean"
          },
          "updateProjects": {
            "type": "boolean"
          },
          "shareProjects": {
            "type": "boolean"
          },
          "deleteProjects": {
            "type": "boolean"
          },
          "updateTasks": {
            "type": "boolean"
          },
          "createTasks": {
            "type": "boolean"
          },
          "deleteTasks": {
            "type": "boolean"
          },
          "assignTasks": {
            "type": "boolean"
          },
          "createLabels": {
            "type": "boolean"
          },
          "updateLabels": {
            "type": "boolean"
          },
          "deleteLabels": {
            "type": "boolean"
          },
          "manageWorkspace": {
            "type": "boolean"
          },
          "manageSettings": {
            "type": "boolean"
          },
          "deleteWorkspace": {
            "type": "boolean"
          },
          "inviteUsers": {
            "type": "boolean"
          },
          "manageTeam": {
            "type": "boolean"
          },
          "updateMembers": {
            "type": "boolean"
          },
          "removeMembers": {
            "type": "boolean"
          }
        },
        "required": [
          "manageProjects",
          "createProjects",
          "updateProjects",
          "shareProjects",
          "deleteProjects",
          "updateTasks",
          "createTasks",
          "deleteTasks",
          "assignTasks",
          "createLabels",
          "updateLabels",
          "deleteLabels",
          "manageWorkspace",
          "manageSettings",
          "deleteWorkspace",
          "inviteUsers",
          "manageTeam",
          "updateMembers",
          "removeMembers"
        ],
        "description": "Whether the caller's roles (and API key scope, if any) allow each named action in the workspace. Mirrors the checks the API enforces."
      },
      "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"
        ]
      },
      "ImportSourceProjectList": {
        "type": "object",
        "properties": {
          "projects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ImportSourceProject"
            }
          }
        },
        "required": [
          "projects"
        ]
      },
      "ImportSourceProject": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "detail": {
            "type": "string",
            "description": "Extra context shown next to the name, such as the source workspace or team."
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "ImportConnection": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/PlankaImportConnection"
          },
          {
            "$ref": "#/components/schemas/PlaneImportConnection"
          },
          {
            "$ref": "#/components/schemas/LinearImportConnection"
          },
          {
            "$ref": "#/components/schemas/JiraImportConnection"
          },
          {
            "$ref": "#/components/schemas/TrelloImportConnection"
          },
          {
            "$ref": "#/components/schemas/KaneoImportConnection"
          }
        ],
        "discriminator": {
          "propertyName": "source",
          "mapping": {
            "planka": "#/components/schemas/PlankaImportConnection",
            "plane": "#/components/schemas/PlaneImportConnection",
            "linear": "#/components/schemas/LinearImportConnection",
            "jira": "#/components/schemas/JiraImportConnection",
            "trello": "#/components/schemas/TrelloImportConnection",
            "kaneo": "#/components/schemas/KaneoImportConnection"
          }
        },
        "description": "Where to import from and how to sign in. Credentials are used only for this request and the import it starts; they are never stored, logged, or returned."
      },
      "PlankaImportConnection": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "planka"
            ]
          },
          "url": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048,
            "description": "Address of the PLANKA instance.",
            "example": "https://planka.example.com"
          },
          "apiKey": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4096,
            "description": "A PLANKA API key. Send it, or username and password. Used only for this import and never stored or logged."
          },
          "username": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Username or email of a PLANKA account, used with password when no API key is sent."
          },
          "password": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4096,
            "description": "Password of that PLANKA account. Used only for this import and never stored or logged."
          }
        },
        "required": [
          "source",
          "url"
        ]
      },
      "PlaneImportConnection": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "plane"
            ]
          },
          "url": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048,
            "description": "Address of the Plane instance, e.g. https://app.plane.so for Plane Cloud.",
            "example": "https://planka.example.com"
          },
          "apiKey": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4096,
            "description": "A Plane personal access token. Used only for this import and never stored or logged."
          },
          "workspaceSlug": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Slug of the Plane workspace to read. Optional when the URL already names it."
          }
        },
        "required": [
          "source",
          "url",
          "apiKey"
        ]
      },
      "LinearImportConnection": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "linear"
            ]
          },
          "apiKey": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4096,
            "description": "A Linear personal API key. Used only for this import and never stored or logged."
          }
        },
        "required": [
          "source",
          "apiKey"
        ]
      },
      "JiraImportConnection": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "jira"
            ]
          },
          "url": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048,
            "description": "Address of the Jira site, e.g. https://your-site.atlassian.net for Jira Cloud, or your own domain for Jira Data Center.",
            "example": "https://your-site.atlassian.net"
          },
          "email": {
            "type": "string",
            "minLength": 1,
            "maxLength": 320,
            "description": "Email of the Atlassian account the API token belongs to. Required for Jira Cloud; leave it out for Jira Data Center."
          },
          "apiToken": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4096,
            "description": "A Jira Cloud API token, sent with email, or a Jira Data Center personal access token, sent without email. Used only for this import and never stored or logged."
          }
        },
        "required": [
          "source",
          "url",
          "apiToken"
        ]
      },
      "TrelloImportConnection": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "trello"
            ]
          },
          "token": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4096,
            "description": "A Trello token authorized for this Kaneo instance. Used only for this import and never stored or logged."
          },
          "apiKey": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "Trello API key, a public app identifier. Defaults to the server's TRELLO_API_KEY."
          }
        },
        "required": [
          "source",
          "token"
        ]
      },
      "KaneoImportConnection": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "kaneo"
            ]
          },
          "url": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048,
            "description": "Address of the Kaneo instance to import from.",
            "example": "https://planka.example.com"
          },
          "apiKey": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4096,
            "description": "An API key from that Kaneo instance. Used only for this import and never stored or logged."
          }
        },
        "required": [
          "source",
          "url",
          "apiKey"
        ]
      },
      "ImportRunEnvelope": {
        "type": "object",
        "properties": {
          "run": {
            "$ref": "#/components/schemas/ImportRun"
          }
        },
        "required": [
          "run"
        ]
      },
      "ImportRun": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "workspaceId": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "planka",
              "plane",
              "linear",
              "jira",
              "trello",
              "kaneo"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "running",
              "completed",
              "failed"
            ],
            "description": "completed once every selected project was attempted, even if some failed; check each project's status. failed means the run itself stopped."
          },
          "includeComments": {
            "type": "boolean"
          },
          "message": {
            "type": [
              "string",
              "null"
            ],
            "description": "Latest progress line while the run is running."
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "projects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ImportRunProject"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "finishedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "workspaceId",
          "source",
          "status",
          "includeComments",
          "message",
          "error",
          "projects",
          "createdAt",
          "finishedAt"
        ]
      },
      "ImportRunProject": {
        "type": "object",
        "properties": {
          "sourceId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "completed",
              "failed"
            ]
          },
          "projectId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The Kaneo project created by the import, once completed."
          },
          "projectSlug": {
            "type": [
              "string",
              "null"
            ]
          },
          "counts": {
            "$ref": "#/components/schemas/ImportCounts"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "sourceId",
          "name",
          "status",
          "projectId",
          "projectSlug",
          "counts",
          "warnings",
          "error"
        ]
      },
      "ImportCounts": {
        "type": "object",
        "properties": {
          "columns": {
            "type": "integer"
          },
          "tasks": {
            "type": "integer"
          },
          "labels": {
            "type": "integer"
          },
          "comments": {
            "type": "integer"
          },
          "assignees": {
            "type": "integer",
            "description": "Tasks that were assigned to a workspace member."
          },
          "relations": {
            "type": "integer"
          }
        },
        "required": [
          "columns",
          "tasks",
          "labels",
          "comments",
          "assignees",
          "relations"
        ]
      },
      "ImportRunList": {
        "type": "object",
        "properties": {
          "runs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ImportRun"
            }
          }
        },
        "required": [
          "runs"
        ]
      },
      "TrelloAuthorizeUrl": {
        "type": "object",
        "properties": {
          "authorizeUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "Trello page where the user approves read access for Kaneo and copies a token. null when the server has no TRELLO_API_KEY; the user then sends their own Trello API key with the token."
          }
        },
        "required": [
          "authorizeUrl"
        ]
      },
      "CurrentUser": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "image": {
            "type": [
              "string",
              "null"
            ]
          },
          "role": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "email",
          "image",
          "role"
        ]
      },
      "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"
        ]
      },
      "AdminUserList": {
        "type": "object",
        "properties": {
          "users": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminUser"
            }
          },
          "total": {
            "type": "integer",
            "description": "Number of users matching the search, across all pages."
          }
        },
        "required": [
          "users",
          "total"
        ]
      },
      "AdminUser": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "emailVerified": {
            "type": "boolean"
          },
          "image": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "role": {
            "type": [
              "string",
              "null"
            ]
          },
          "banned": {
            "type": "boolean"
          },
          "banReason": {
            "type": [
              "string",
              "null"
            ]
          },
          "banExpires": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "email",
          "emailVerified",
          "image",
          "createdAt",
          "updatedAt",
          "role",
          "banned",
          "banReason",
          "banExpires"
        ]
      },
      "AdminWorkspaceList": {
        "type": "object",
        "properties": {
          "workspaces": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminWorkspace"
            }
          },
          "total": {
            "type": "integer",
            "description": "Number of workspaces matching the search, across all pages."
          }
        },
        "required": [
          "workspaces",
          "total"
        ]
      },
      "AdminWorkspace": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "memberCount": {
            "type": "integer"
          },
          "projectCount": {
            "type": "integer"
          },
          "owners": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "email": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "name",
                "email"
              ]
            }
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "createdAt",
          "memberCount",
          "projectCount",
          "owners"
        ]
      },
      "AdminWorkspaceMember": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "image": {
            "type": [
              "string",
              "null"
            ]
          },
          "role": {
            "type": "string"
          },
          "joinedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "userId",
          "name",
          "email",
          "image",
          "role",
          "joinedAt"
        ]
      }
    },
    "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": "getPublicProject",
        "tags": [
          "Projects"
        ],
        "summary": "Get a public project board",
        "description": "Read a public board in bounded task pages. Visibility is checked before loading tasks. Continue through pagination.totalPages for all tasks and through relatedPage/pagination.relatedTotalPages for their complete related records.",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "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": "integer",
              "minimum": 1,
              "maximum": 1000000
            },
            "required": false,
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000000
            },
            "required": false,
            "name": "relatedPage",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "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"
          }
        ],
        "responses": {
          "200": {
            "description": "A public board page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicBoardPage"
                }
              }
            }
          },
          "400": {
            "description": "Invalid pagination or filters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Project is not public",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "503": {
            "description": "Task list request timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/public-project/{id}/description": {
      "get": {
        "operationId": "getPublicProjectDescriptionPage",
        "tags": [
          "Projects"
        ],
        "summary": "Read a public project description page",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 2000000000,
              "default": 0
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,10}$"
            },
            "required": false,
            "name": "version",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Public project description page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskDescriptionPage"
                }
              }
            }
          },
          "400": {
            "description": "Invalid description cursor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Public project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Description changed or no longer public",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "503": {
            "description": "Description request timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/public-project/{id}/task/{taskId}/description": {
      "get": {
        "operationId": "getPublicTaskDescriptionPage",
        "tags": [
          "Projects"
        ],
        "summary": "Read a public task description page",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "taskId",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 2000000000,
              "default": 0
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,10}$"
            },
            "required": false,
            "name": "version",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Public task description page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskDescriptionPage"
                }
              }
            }
          },
          "400": {
            "description": "Invalid description cursor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Public task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Description changed or no longer public",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "503": {
            "description": "Description request timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/calendar-feed/{token}/calendar.ics": {
      "get": {
        "operationId": "getCalendarFeed",
        "tags": [
          "Calendar feeds"
        ],
        "summary": "Subscribe to a calendar feed",
        "description": "Read scheduled project tasks using a secret calendar feed link. Anyone with the link can read matching task titles, descriptions, and dates. Responses are streamed; descriptions longer than 4096 characters and titles or calendar names longer than 1024 characters are truncated with an ellipsis.",
        "security": [],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^[a-f0-9]{64}$"
            },
            "required": true,
            "name": "token",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "iCalendar feed",
            "content": {
              "text/calendar": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Invalid feed token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Calendar feed not found or revoked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/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"
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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": "Staged upload owned by another user, or no access to the asset's project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Asset not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                    },
                    "projectAccess": {
                      "type": "string",
                      "enum": [
                        "all",
                        "selected"
                      ],
                      "description": "\"all\" gives access to every project once accepted; \"selected\" limits the member to projectIds."
                    },
                    "projectIds": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Projects the invitation grants when projectAccess is \"selected\". Only projects the viewer can access are listed."
                    }
                  },
                  "required": [
                    "id",
                    "email",
                    "role",
                    "organizationId",
                    "inviterId",
                    "status",
                    "expiresAt",
                    "organizationName",
                    "organizationSlug",
                    "inviterEmail",
                    "projectAccess",
                    "projectIds"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/auth/organization/invite-member": {
      "post": {
        "tags": [
          "Organization Management"
        ],
        "operationId": "inviteOrganizationMember",
        "summary": "Invite Organization Member",
        "description": "Create or resend an invitation. Email delivery failures return 502; the invitation remains pending and can be resent after correcting SMTP settings.",
        "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"
                        }
                      }
                    ]
                  },
                  "projectAccess": {
                    "type": "string",
                    "enum": [
                      "all",
                      "selected"
                    ],
                    "description": "\"all\" (the default) gives access to every project. \"selected\" limits the new member to projectIds once they accept."
                  },
                  "projectIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Projects the new member can access when projectAccess is \"selected\". They must belong to the workspace, and an inviter whose own access is limited can only choose projects they can access."
                  }
                },
                "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"
                    },
                    "projectAccess": {
                      "type": "string",
                      "enum": [
                        "all",
                        "selected"
                      ],
                      "description": "\"all\" gives access to every project once accepted; \"selected\" limits the member to projectIds."
                    },
                    "projectIds": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Projects the invitation grants when projectAccess is \"selected\". Only projects the viewer can access are listed."
                    }
                  },
                  "required": [
                    "id",
                    "email",
                    "role",
                    "organizationId",
                    "inviterId",
                    "status",
                    "expiresAt",
                    "createdAt",
                    "projectAccess",
                    "projectIds"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          },
          "502": {
            "description": "Invitation saved, but email delivery failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string",
                      "enum": [
                        "INVITATION_EMAIL_FAILED"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "code",
                    "message"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/auth/organization/list-invitations": {
      "get": {
        "tags": [
          "Organization Management"
        ],
        "operationId": "listOrganizationInvitations",
        "summary": "List Organization Invitations",
        "description": "List Organization Invitations",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "organizationId",
            "in": "query"
          }
        ],
        "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"
                      },
                      "inviterId": {
                        "type": "string"
                      },
                      "status": {
                        "type": "string"
                      },
                      "expiresAt": {
                        "type": "string"
                      },
                      "createdAt": {
                        "type": "string"
                      },
                      "projectAccess": {
                        "type": "string",
                        "enum": [
                          "all",
                          "selected"
                        ],
                        "description": "\"all\" gives access to every project once accepted; \"selected\" limits the member to projectIds."
                      },
                      "projectIds": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "Projects the invitation grants when projectAccess is \"selected\". Only projects the viewer can access are listed."
                      }
                    },
                    "required": [
                      "id",
                      "email",
                      "role",
                      "organizationId",
                      "inviterId",
                      "status",
                      "expiresAt",
                      "createdAt",
                      "projectAccess",
                      "projectIds"
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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,
                    "maxItems": 10
                  },
                  "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"
                      ]
                    },
                    "maxItems": 2
                  },
                  "response_types": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "code"
                      ]
                    },
                    "minItems": 1,
                    "maxItems": 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",
              "minLength": 1,
              "maxLength": 128
            },
            "required": true,
            "name": "client_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 2048
            },
            "required": true,
            "name": "redirect_uri",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{43}$",
              "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",
              "maxLength": 1024
            },
            "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",
              "minLength": 1,
              "maxLength": 128
            },
            "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",
              "minLength": 1,
              "maxLength": 128
            },
            "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"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/project/{id}/move": {
      "put": {
        "operationId": "moveProject",
        "tags": [
          "Projects"
        ],
        "summary": "Move a project to another workspace",
        "description": "Move a project and its tasks. Requires update and delete permission in the source, plus project creation and workspace settings management permission in the destination. Remove cross-project task relationships before moving.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "workspaceId": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "workspaceId"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Project moved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MovedProject"
                }
              }
            }
          },
          "400": {
            "description": "Invalid destination or same workspace",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "402": {
            "description": "Destination workspace plan has expired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing permission in the source or destination workspace",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or destination workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Project key conflict or cross-project task relationships",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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"
                  }
                },
                "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Missing project:create permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Another project in the workspace uses this key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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"
                  }
                },
                "required": [
                  "name",
                  "icon",
                  "slug",
                  "description",
                  "isPublic"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, missing project:update, or missing project:share when visibility changes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Another project in the workspace uses the new key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:delete permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/project/{id}/background": {
      "get": {
        "operationId": "getProjectBackground",
        "tags": [
          "Projects"
        ],
        "summary": "Download project background",
        "description": "Download the current project board background image.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The project background image",
            "content": {
              "image/*": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "304": {
            "description": "Not modified"
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or project background not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteProjectBackground",
        "tags": [
          "Projects"
        ],
        "summary": "Delete project background",
        "description": "Remove the current project board background image.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Project background removed"
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Missing project:update permission, or no access to a listed project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Another project in the workspace uses this key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/project/{id}/background-upload": {
      "put": {
        "operationId": "uploadProjectBackground",
        "tags": [
          "Projects"
        ],
        "summary": "Prepare project background upload",
        "description": "Create a presigned background image upload URL for a project.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contentType": {
                    "type": "string"
                  },
                  "size": {
                    "type": "number"
                  }
                },
                "required": [
                  "contentType",
                  "size"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Background image upload URL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectBackgroundUpload"
                }
              }
            }
          },
          "400": {
            "description": "Invalid image upload request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          },
          "503": {
            "description": "Image uploads are not configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/project/{id}/background-upload/finalize": {
      "post": {
        "operationId": "finalizeProjectBackgroundUpload",
        "tags": [
          "Projects"
        ],
        "summary": "Finalize project background upload",
        "description": "Save an uploaded image as the project's board background.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "key": {
                    "type": "string"
                  },
                  "contentType": {
                    "type": "string"
                  },
                  "version": {
                    "type": "string"
                  },
                  "size": {
                    "type": "number"
                  }
                },
                "required": [
                  "key",
                  "contentType",
                  "version",
                  "size"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Finalized project background",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectBackgroundFinalize"
                }
              }
            }
          },
          "400": {
            "description": "Invalid image upload request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          },
          "500": {
            "description": "Failed to save the project background",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/calendar-feed/project/{projectId}": {
      "get": {
        "operationId": "listCalendarFeeds",
        "tags": [
          "Calendar feeds"
        ],
        "summary": "List project calendar feeds",
        "description": "List secret calendar subscription links. Requires project sharing permission.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Calendar feeds",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CalendarFeed"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project sharing permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "post": {
        "operationId": "createCalendarFeed",
        "tags": [
          "Calendar feeds"
        ],
        "summary": "Create a calendar feed",
        "description": "Create a calendar subscription matching any selected label, or all project tasks when no labels are selected. Tasks need a start or due date. All-day dates use the supplied time zone. Creating a missing workspace label definition also requires label:create permission.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "labelIds": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1
                    },
                    "maxItems": 100,
                    "default": [],
                    "description": "Match any selected label. Omit or leave empty to include all scheduled project tasks."
                  },
                  "timeZone": {
                    "type": "string",
                    "default": "UTC"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Calendar feed created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CalendarFeed"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, missing project:share permission, or missing label:create permission for a new workspace label definition",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/calendar-feed/project/{projectId}/{id}": {
      "delete": {
        "operationId": "revokeCalendarFeed",
        "tags": [
          "Calendar feeds"
        ],
        "summary": "Revoke a calendar feed",
        "description": "Revoke a calendar subscription link, preventing further access through it.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Calendar feed revoked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "success"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project sharing permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or calendar feed not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/task/{id}/description": {
      "get": {
        "operationId": "getTaskDescriptionPage",
        "tags": [
          "Tasks"
        ],
        "summary": "Read a description page",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 2000000000,
              "default": 0
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,10}$"
            },
            "required": false,
            "name": "version",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Description page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskDescriptionPage"
                }
              }
            }
          },
          "400": {
            "description": "Invalid offset or version",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Description changed; reload from offset zero",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          },
          "503": {
            "description": "Description request timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/task/description-matches/{projectId}": {
      "get": {
        "operationId": "findDeferredTaskDescriptions",
        "tags": [
          "Tasks"
        ],
        "summary": "Search descriptions omitted from task lists",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256
            },
            "required": true,
            "name": "query",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "required": false,
            "name": "after",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Matching task IDs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskDescriptionMatches"
                }
              }
            }
          },
          "400": {
            "description": "Invalid search query or cursor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          },
          "503": {
            "description": "Description search timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/task/assigned": {
      "get": {
        "operationId": "listAssignedTasks",
        "tags": [
          "Tasks"
        ],
        "summary": "List my assigned tasks",
        "description": "Get the open tasks assigned to the caller across a workspace's active projects. Completed and archived tasks are excluded. Ordered by due date (undated last), then priority. At most 100 tasks are returned; total counts all of them. Set countOnly=true to return just that total without loading task rows or labels.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "workspaceId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ],
              "description": "Return only the total, with an empty tasks array, without loading task rows or labels."
            },
            "required": false,
            "description": "Return only the total, with an empty tasks array, without loading task rows or labels.",
            "name": "countOnly",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Open tasks assigned to the caller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssignedTasks"
                }
              }
            }
          },
          "400": {
            "description": "Invalid workspace ID or query parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Missing project:read or task:read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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. Responses always contain at most 100 tasks (50 by default). Continue through pagination.totalPages for the whole board, and for each task page follow relatedPage through pagination.relatedTotalPages for all labels, links and column metadata. Filters and sorting apply before pagination. Descriptions larger than 64 KiB are omitted with descriptionDeferred=true; read the task detail or description pages for full text.",
        "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": "integer",
              "minimum": 1,
              "maximum": 1000000
            },
            "required": false,
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000000
            },
            "required": false,
            "name": "relatedPage",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "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"
          }
        ],
        "responses": {
          "200": {
            "description": "The project board",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BoardResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          },
          "503": {
            "description": "Task list request timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/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
                  },
                  "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing the permission the operation needs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "No tasks found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Tasks changed projects; retry the operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/task/draft-upload/{projectId}": {
      "post": {
        "operationId": "stageTaskAssetUpload",
        "tags": [
          "Tasks"
        ],
        "summary": "Stage a task attachment",
        "description": "Upload an attachment before submitting a task. Staged assets are private to the uploader and expire after 24 hours.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "projectId",
            "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"
                    ]
                  }
                },
                "required": [
                  "filename",
                  "contentType",
                  "size",
                  "surface"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Presigned upload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskImageUpload"
                }
              }
            }
          },
          "400": {
            "description": "Invalid upload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Missing task:create permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          },
          "503": {
            "description": "Storage unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/task/draft-upload/{projectId}/finalize": {
      "post": {
        "operationId": "finalizeStagedTaskAsset",
        "tags": [
          "Tasks"
        ],
        "summary": "Finalize a staged task attachment",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "projectId",
            "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"
                    ]
                  }
                },
                "required": [
                  "key",
                  "filename",
                  "contentType",
                  "size",
                  "surface"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Staged attachment",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskImageAsset"
                }
              }
            }
          },
          "400": {
            "description": "Invalid upload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Missing task:create permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Upload already attached",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          },
          "503": {
            "description": "Storage unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/task/reorder": {
      "post": {
        "operationId": "reorderTasks",
        "tags": [
          "Tasks"
        ],
        "summary": "Reorder or move cards",
        "description": "Atomically update positions and optional column status for cards in one project. Other task fields are preserved.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "projectId": {
                    "type": "string"
                  },
                  "expectedTasks": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "position": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "minimum": 0,
                          "maximum": 2147483646
                        },
                        "status": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "position",
                        "status"
                      ]
                    },
                    "description": "Previous complete contents of the affected columns; stale snapshots return 409"
                  },
                  "tasks": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "position": {
                          "type": "integer",
                          "minimum": 0,
                          "maximum": 2147483646
                        },
                        "status": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "position"
                      ]
                    },
                    "minItems": 1
                  }
                },
                "required": [
                  "projectId",
                  "tasks"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated card positions and statuses",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "position": {
                        "type": "number"
                      },
                      "status": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "id",
                      "position",
                      "status"
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid positions or column",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found, or tasks do not belong to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Board changed or task moved; refresh before reordering",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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."
                  },
                  "draftAssetIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 100
                  },
                  "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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:create permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/task/duplicate/{id}": {
      "post": {
        "operationId": "duplicateTask",
        "tags": [
          "Tasks"
        ],
        "summary": "Duplicate a task",
        "description": "Copy a task into the same project and column, including custom fields, labels, description assets and same-workspace parent links. Copying parent links also requires task:update. Comments, time entries and child tasks are not copied.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The duplicated task",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "description": "Invalid task fields or request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, missing task:create, or missing task:update when copying parent links",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task or project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Task column has reached its capacity",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          },
          "503": {
            "description": "Unable to copy task attachments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/task/by-ticket-id/{ticketId}": {
      "get": {
        "operationId": "getTaskByTicketId",
        "tags": [
          "Tasks"
        ],
        "summary": "Get task by ticket ID",
        "description": "Get a single task by its project key and number, such as KAN-12. A match in an active project takes precedence, then the most recently archived project. If the ticket ID still matches multiple accessible tasks, narrow the lookup to a workspace with workspaceId or workspaceSlug, or to a single project with projectId.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 128,
              "description": "Project key and task number, e.g. KAN-12."
            },
            "required": true,
            "description": "Project key and task number, e.g. KAN-12.",
            "name": "ticketId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Select a workspace if the ticket ID exists in more than one."
            },
            "required": false,
            "description": "Select a workspace if the ticket ID exists in more than one.",
            "name": "workspaceId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "description": "Select a workspace by its slug instead of its ID."
            },
            "required": false,
            "description": "Select a workspace by its slug instead of its ID.",
            "name": "workspaceSlug",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Select a project if the ticket ID exists more than once."
            },
            "required": false,
            "description": "Select a project if the ticket ID exists more than once.",
            "name": "projectId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Task details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskByTicketId"
                }
              }
            }
          },
          "400": {
            "description": "Invalid ticket ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "No accessible task has this ticket ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Ticket ID matches multiple accessible tasks",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/task/{id}": {
      "get": {
        "operationId": "getTask",
        "tags": [
          "Tasks"
        ],
        "summary": "Get task",
        "description": "Get a single task by ID, with its assignee name. The board view omits descriptions above 64 KiB and includes task and same-project parent subtask progress.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "detail",
                "board"
              ]
            },
            "required": false,
            "name": "view",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Task details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskWithAssignee"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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",
                    "description": "Omit to preserve the existing description when updating a list summary."
                  },
                  "startDate": {
                    "type": "string"
                  },
                  "dueDate": {
                    "type": "string"
                  },
                  "priority": {
                    "type": "string",
                    "enum": [
                      "no-priority",
                      "low",
                      "medium",
                      "high",
                      "urgent"
                    ]
                  },
                  "status": {
                    "type": "string"
                  },
                  "projectId": {
                    "type": "string"
                  },
                  "position": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 2147483646
                  },
                  "userId": {
                    "type": "string"
                  }
                },
                "required": [
                  "title",
                  "priority",
                  "status",
                  "projectId",
                  "position"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated task",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update or task:assign permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:delete permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Task changed projects; retry the operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task or destination project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Task or project moved concurrently; retry the move",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:create permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:assign permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found, or assignee is not a member of the workspace",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          },
          "503": {
            "description": "Image uploads are not configured on this instance",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "The slug is reserved, or already used in this project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Column not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Column not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "The column still contains tasks",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/activity/workspace/{workspaceId}": {
      "get": {
        "operationId": "getWorkspaceActivities",
        "tags": [
          "Activity"
        ],
        "summary": "Get recent workspace activity",
        "description": "Get the 20 most recent task events across a workspace's active projects from the last 30 days, newest first. Each event carries a short plain-text excerpt instead of its full content.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Recent activity in the workspace",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WorkspaceActivity"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Missing project:read or task:read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/activity/{taskId}": {
      "get": {
        "operationId": "getActivities",
        "tags": [
          "Activity"
        ],
        "summary": "Get task activity",
        "description": "Get a task's activity feed, newest first: comments alongside system events such as status and assignee changes. Set limit to request a bounded preview; omit it for the full feed.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "taskId",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Maximum number of recent activities; omit for the full feed."
            },
            "required": false,
            "description": "Maximum number of recent activities; omit for the full feed.",
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of activities for the task",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Activity"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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 comment activity submitted through the generic endpoint",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
                    "maxLength": 10000
                  }
                },
                "required": [
                  "taskId",
                  "comment"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The created comment",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Activity"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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",
                    "maxLength": 10000
                  }
                },
                "required": [
                  "activityId",
                  "comment"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated comment",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Activity"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Not the author, or no access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Activity or comment not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Not the author, or no access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Activity or comment not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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,
                    "maxLength": 10000
                  },
                  "externalUserName": {
                    "type": "string",
                    "maxLength": 120,
                    "description": "Attribution for an imported comment. Requires workspace:manage_settings and externalSource; otherwise ignored."
                  },
                  "externalSource": {
                    "type": "string",
                    "enum": [
                      "planka",
                      "trello",
                      "jira",
                      "plane",
                      "linear",
                      "kaneo"
                    ],
                    "description": "The tool the comment was imported from. Supplying external attribution requires workspace:manage_settings."
                  }
                },
                "required": [
                  "content"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The created comment",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Activity"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, missing task:update permission, or external attribution without workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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,
                    "maxLength": 10000
                  }
                },
                "required": [
                  "content"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated comment",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Activity"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Not the author, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Comment not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Not the author, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Comment not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Time entry not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Time entry not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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 body or timestamps",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Missing label:create permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace or task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "The workspace label is being deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Label not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing label:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Label not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "The workspace label is being deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteLabel",
        "tags": [
          "Labels"
        ],
        "summary": "Delete label",
        "description": "Delete a label by ID. Large workspace cascades remove at most 25 task copies per request. Repeat DELETE with the same ID after HTTP 202 until HTTP 200 completes the operation. The persisted start boundary allows safe resumption after a disconnect. HTTP 429 asks the caller to retry later.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Label deleted successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Label"
                }
              }
            }
          },
          "202": {
            "description": "Deletion has more batches; repeat the same request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PendingLabelDeletion"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing label:delete permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Label not found, or the label's task no longer exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Deletion capacity is busy; retry after Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/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": "Label and task belong to different workspaces",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing label:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Label or task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "The workspace label is being deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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": "Label is not assigned to a task",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing label:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Label or task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/notification": {
      "get": {
        "operationId": "listNotifications",
        "tags": [
          "Notifications"
        ],
        "summary": "List notifications",
        "description": "Get up to 50 notifications for the current user, read and unread. Optionally limit them to one workspace before applying the limit.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Limit notifications to resources currently in this workspace, plus user-wide notifications with no resource. Omit to include all workspaces."
            },
            "required": false,
            "description": "Limit notifications to resources currently in this workspace, plus user-wide notifications with no resource. Omit to include all workspaces.",
            "name": "workspaceId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of notifications",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Notification"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Notification not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/notification/{id}/unread": {
      "patch": {
        "operationId": "markNotificationAsUnread",
        "tags": [
          "Notifications"
        ],
        "summary": "Mark notification unread",
        "description": "Mark one notification as unread again. 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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Notification not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/notification/read-all": {
      "patch": {
        "operationId": "markAllNotificationsAsRead",
        "tags": [
          "Notifications"
        ],
        "summary": "Mark all read",
        "description": "Mark notifications for the current user as read, optionally limited to one workspace.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Limit notifications to resources currently in this workspace, plus user-wide notifications with no resource. Omit to include all workspaces."
            },
            "required": false,
            "description": "Limit notifications to resources currently in this workspace, plus user-wide notifications with no resource. Omit to include all workspaces.",
            "name": "workspaceId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "All notifications marked as read",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationBulkResult"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/notification/clear-all": {
      "delete": {
        "operationId": "clearAllNotifications",
        "tags": [
          "Notifications"
        ],
        "summary": "Clear all",
        "description": "Permanently delete notifications for the current user, optionally limited to one workspace. This cannot be undone.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Limit notifications to resources currently in this workspace, plus user-wide notifications with no resource. Omit to include all workspaces."
            },
            "required": false,
            "description": "Limit notifications to resources currently in this workspace, plus user-wide notifications with no resource. Omit to include all workspaces.",
            "name": "workspaceId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "All notifications cleared",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationBulkResult"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/notification/clear-read": {
      "delete": {
        "operationId": "clearReadNotifications",
        "tags": [
          "Notifications"
        ],
        "summary": "Clear read notifications",
        "description": "Permanently delete the current user's read notifications, optionally limited to one workspace. Unread notifications are kept. This cannot be undone.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Limit notifications to resources currently in this workspace, plus user-wide notifications with no resource. Omit to include all workspaces."
            },
            "required": false,
            "description": "Limit notifications to resources currently in this workspace, plus user-wide notifications with no resource. Omit to include all workspaces.",
            "name": "workspaceId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Read notifications cleared",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationBulkResult"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/notification/{id}": {
      "delete": {
        "operationId": "deleteNotification",
        "tags": [
          "Notifications"
        ],
        "summary": "Delete notification",
        "description": "Permanently delete one notification. 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": "Notification deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationBulkResult"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Notification not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the workspace",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the workspace",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace rule not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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,
              "maxLength": 512
            },
            "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/integration-sync/project/{projectId}/{provider}": {
      "get": {
        "operationId": "getIntegrationSyncRules",
        "tags": [
          "Integration sync"
        ],
        "summary": "Get sync rules and current task scope",
        "description": "Workspace members with project and task read permissions can inspect saved rules. Rules remain active when advanced mode is hidden. Paused issue links are preserved; eligible paused tasks require review before resuming.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "github",
                "gitea",
                "gitlab"
              ]
            },
            "required": true,
            "name": "provider",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "after",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Saved rules and scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationSyncPreview"
                }
              }
            }
          },
          "400": {
            "description": "Invalid rule or workspace label",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing required permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project, integration, or linked task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Configuration, impact or comparison changed; review again",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "patch": {
        "operationId": "saveIntegrationSyncRules",
        "tags": [
          "Integration sync"
        ],
        "summary": "Apply a previewed sync rule",
        "description": "Save shared integration rules only if the preview is still current. Excluded links are paused, never deleted. Newly matching unlinked tasks are exported through the integration event path. Paused links require explicit review to resume.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "github",
                "gitea",
                "gitlab"
              ]
            },
            "required": true,
            "name": "provider",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "rules": {
                    "type": "object",
                    "properties": {
                      "outgoing": {
                        "oneOf": [
                          {
                            "type": "object",
                            "properties": {
                              "mode": {
                                "type": "string",
                                "enum": [
                                  "all"
                                ]
                              }
                            },
                            "required": [
                              "mode"
                            ]
                          },
                          {
                            "type": "object",
                            "properties": {
                              "mode": {
                                "type": "string",
                                "enum": [
                                  "labels"
                                ]
                              },
                              "match": {
                                "type": "string",
                                "enum": [
                                  "any",
                                  "all"
                                ]
                              },
                              "labels": {
                                "type": "array",
                                "items": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 128
                                },
                                "minItems": 1,
                                "maxItems": 50
                              }
                            },
                            "required": [
                              "mode",
                              "match",
                              "labels"
                            ]
                          }
                        ],
                        "description": "Kaneo workspace label IDs controlling task sync. Missing labels pause sync."
                      },
                      "incoming": {
                        "oneOf": [
                          {
                            "type": "object",
                            "properties": {
                              "mode": {
                                "type": "string",
                                "enum": [
                                  "all"
                                ]
                              }
                            },
                            "required": [
                              "mode"
                            ]
                          },
                          {
                            "type": "object",
                            "properties": {
                              "mode": {
                                "type": "string",
                                "enum": [
                                  "labels"
                                ]
                              },
                              "match": {
                                "type": "string",
                                "enum": [
                                  "any",
                                  "all"
                                ]
                              },
                              "labels": {
                                "type": "array",
                                "items": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 128
                                },
                                "minItems": 1,
                                "maxItems": 50
                              }
                            },
                            "required": [
                              "mode",
                              "match",
                              "labels"
                            ]
                          }
                        ],
                        "description": "Exact repository label names controlling which issues can be imported."
                      }
                    },
                    "required": [
                      "outgoing",
                      "incoming"
                    ]
                  },
                  "previewToken": {
                    "type": "string",
                    "minLength": 64,
                    "maxLength": 64
                  }
                },
                "required": [
                  "rules",
                  "previewToken"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved rules and current scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationSyncPreview"
                }
              }
            }
          },
          "400": {
            "description": "Invalid rule or workspace label",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing required permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project, integration, or linked task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Configuration, impact or comparison changed; review again",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/integration-sync/project/{projectId}/{provider}/preview": {
      "post": {
        "operationId": "previewIntegrationSyncRules",
        "tags": [
          "Integration sync"
        ],
        "summary": "Preview a sync rule change",
        "description": "Returns matching tasks, new exports, paused links and a token bound to the current integration and impact. Outgoing labels are workspace label IDs; incoming labels are exact repository label names.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "github",
                "gitea",
                "gitlab"
              ]
            },
            "required": true,
            "name": "provider",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "rules": {
                    "type": "object",
                    "properties": {
                      "outgoing": {
                        "oneOf": [
                          {
                            "type": "object",
                            "properties": {
                              "mode": {
                                "type": "string",
                                "enum": [
                                  "all"
                                ]
                              }
                            },
                            "required": [
                              "mode"
                            ]
                          },
                          {
                            "type": "object",
                            "properties": {
                              "mode": {
                                "type": "string",
                                "enum": [
                                  "labels"
                                ]
                              },
                              "match": {
                                "type": "string",
                                "enum": [
                                  "any",
                                  "all"
                                ]
                              },
                              "labels": {
                                "type": "array",
                                "items": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 128
                                },
                                "minItems": 1,
                                "maxItems": 50
                              }
                            },
                            "required": [
                              "mode",
                              "match",
                              "labels"
                            ]
                          }
                        ],
                        "description": "Kaneo workspace label IDs controlling task sync. Missing labels pause sync."
                      },
                      "incoming": {
                        "oneOf": [
                          {
                            "type": "object",
                            "properties": {
                              "mode": {
                                "type": "string",
                                "enum": [
                                  "all"
                                ]
                              }
                            },
                            "required": [
                              "mode"
                            ]
                          },
                          {
                            "type": "object",
                            "properties": {
                              "mode": {
                                "type": "string",
                                "enum": [
                                  "labels"
                                ]
                              },
                              "match": {
                                "type": "string",
                                "enum": [
                                  "any",
                                  "all"
                                ]
                              },
                              "labels": {
                                "type": "array",
                                "items": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 128
                                },
                                "minItems": 1,
                                "maxItems": 50
                              }
                            },
                            "required": [
                              "mode",
                              "match",
                              "labels"
                            ]
                          }
                        ],
                        "description": "Exact repository label names controlling which issues can be imported."
                      }
                    },
                    "required": [
                      "outgoing",
                      "incoming"
                    ]
                  }
                },
                "required": [
                  "rules"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Proposed rule impact",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationSyncPreview"
                }
              }
            }
          },
          "400": {
            "description": "Invalid rule or workspace label",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing required permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project, integration, or linked task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Configuration, impact or comparison changed; review again",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/integration-sync/project/{projectId}/{provider}/links/{linkId}/review": {
      "get": {
        "operationId": "reviewIntegrationSyncResume",
        "tags": [
          "Integration sync"
        ],
        "summary": "Compare a paused task with its external issue",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "github",
                "gitea",
                "gitlab"
              ]
            },
            "required": true,
            "name": "provider",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "linkId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Current values and comparison token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationSyncResumePreview"
                }
              }
            }
          },
          "400": {
            "description": "Invalid rule or workspace label",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing required permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project, integration, or linked task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Configuration, impact or comparison changed; review again",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          },
          "502": {
            "description": "External issue unavailable; sync remains paused",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/integration-sync/project/{projectId}/{provider}/links/{linkId}/resume": {
      "post": {
        "operationId": "resumeIntegrationSync",
        "tags": [
          "Integration sync"
        ],
        "summary": "Resume a reviewed issue link",
        "description": "Explicitly choose the current Kaneo or repository title, description and open/closed state. Existing links are reused; historical comments are not replayed. The task must still match its outgoing rule. A changed comparison requires another review.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "github",
                "gitea",
                "gitlab"
              ]
            },
            "required": true,
            "name": "provider",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true,
            "name": "linkId",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "token": {
                    "type": "string",
                    "minLength": 64,
                    "maxLength": 64
                  },
                  "source": {
                    "type": "string",
                    "enum": [
                      "kaneo",
                      "provider"
                    ]
                  }
                },
                "required": [
                  "token",
                  "source"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sync resumed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "success"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid rule or workspace label",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing required permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project, integration, or linked task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Comparison changed or synchronization is busy; review or retry",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          },
          "502": {
            "description": "External issue unavailable; sync remains paused",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/github-integration/repositories/{projectId}": {
      "get": {
        "operationId": "listGitHubRepositories",
        "tags": [
          "GitHub"
        ],
        "summary": "List GitHub repositories",
        "description": "List the repositories reachable through the installed GitHub App that the caller administers, for picking one to link. Without `search`, each request reads one page of one installation. With `search`, the server filters by name and description before checking access and keeps scanning later pages and installations within a fixed budget. Follow `nextPage` until it is null to see every repository.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]{0,5}$",
              "default": "1"
            },
            "required": false,
            "name": "installationPage",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]{0,5}$",
              "default": "1"
            },
            "required": false,
            "name": "repositoryPage",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 100,
              "description": "Case-insensitive match on the repository full name or description. When set, one request scans up to 10 pages of 100 repositories across installations and returns every match it finds, with `nextPage` set to resume the scan."
            },
            "required": false,
            "description": "Case-insensitive match on the repository full name or description. When set, one request scans up to 10 pages of 100 repositories across installations and returns every match it finds, with `nextPage` set to resume the scan.",
            "name": "search",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Repositories reachable through the installed App",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GitHubRepositoryList"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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,
                    "maxLength": 100
                  },
                  "repositoryName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  }
                },
                "required": [
                  "projectId",
                  "repositoryOwner",
                  "repositoryName"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verification result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GitHubVerificationResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "post": {
        "operationId": "createGitHubIntegration",
        "tags": [
          "GitHub"
        ],
        "summary": "Create GitHub integration",
        "description": "Link a project to a GitHub repository. Disconnect first to switch repositories; existing issue and pull request links cannot be reused for another 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,
                    "maxLength": 100
                  },
                  "repositoryName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  }
                },
                "required": [
                  "repositoryOwner",
                  "repositoryName"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The stored integration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedGitHubIntegration"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Integration changed or another repository is already linked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Integration changed or another repository is already linked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or GitHub integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/github-integration/import-issues": {
      "post": {
        "operationId": "importGitHubIssues",
        "tags": [
          "GitHub"
        ],
        "summary": "Import GitHub issues",
        "description": "Import open issues and link open pull requests in bounded steps. Existing tasks are updated. Continue 202 responses with the returned runId until 200; the same runId safely retries completion. Progress is saved after each page. New calls without runId resume an unfinished import or start a new one after completion.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "projectId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 128
                  },
                  "runId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 128
                  }
                },
                "required": [
                  "projectId"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Completed import summary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssueImportResult"
                }
              }
            }
          },
          "202": {
            "description": "Saved import progress; continue with runId",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IssueImportResult"
                }
              }
            }
          },
          "400": {
            "description": "projectId is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:create or task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Integration or import changed; refresh before resuming",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Import busy; retry after one second",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "502": {
            "description": "Provider unavailable or invalid page; progress is saved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/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 invalid Gitea credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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. Repository permission failures are reported in the body; invalid credentials and upstream errors return an error status. Omit accessToken to use the saved token for the unchanged base 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,
                    "description": "Omit to verify with this project's saved token. The base URL must match the saved integration."
                  },
                  "repositoryOwner": {
                    "type": "string",
                    "minLength": 1
                  },
                  "repositoryName": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "projectId",
                  "baseUrl",
                  "repositoryOwner",
                  "repositoryName"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verification result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GiteaVerificationResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, or invalid Gitea credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Kaneo authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          },
          "500": {
            "description": "Gitea verification failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Integration changed; refresh before updating settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or Gitea integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:create or task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/gitlab-integration/projects": {
      "post": {
        "operationId": "listGitlabProjects",
        "tags": [
          "GitLab"
        ],
        "summary": "List GitLab projects",
        "description": "List the projects a GitLab token is a member of, 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
                  },
                  "tokenType": {
                    "type": "string",
                    "enum": [
                      "private",
                      "bearer"
                    ],
                    "description": "`private` sends the token in PRIVATE-TOKEN, which is what personal, project and group access tokens expect. `bearer` sends it in Authorization, for an OAuth2 token you already hold. Defaults to `private`."
                  }
                },
                "required": [
                  "projectId",
                  "baseUrl",
                  "accessToken"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Accessible projects",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GitlabProjectList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "GitLab rejected the token, or the instance is unreachable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/gitlab-integration/verify": {
      "post": {
        "operationId": "verifyGitlabAccess",
        "tags": [
          "GitLab"
        ],
        "summary": "Verify GitLab access",
        "description": "Check that the base URL is a GitLab instance and that the token can reach the project with the permissions Kaneo needs. An unreachable instance, a missing project, or insufficient permissions are reported in a 200 body so the form can explain them; a token GitLab rejects outright is a 401.",
        "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
                  },
                  "tokenType": {
                    "type": "string",
                    "enum": [
                      "private",
                      "bearer"
                    ],
                    "description": "`private` sends the token in PRIVATE-TOKEN, which is what personal, project and group access tokens expect. `bearer` sends it in Authorization, for an OAuth2 token you already hold. Defaults to `private`."
                  },
                  "projectPath": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Full path of the GitLab project, including any nested groups, for example acme/platform/web."
                  }
                },
                "required": [
                  "projectId",
                  "baseUrl",
                  "accessToken",
                  "projectPath"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verification result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GitlabVerificationResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "GitLab rejected the token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/gitlab-integration/project/{projectId}": {
      "get": {
        "operationId": "getGitlabIntegration",
        "tags": [
          "GitLab"
        ],
        "summary": "Get GitLab integration",
        "description": "Get the GitLab integration for a project, or null when none is configured. The masked access token and the webhook secret are included only for callers with workspace:manage_settings.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "GitLab integration details, or null",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GitlabIntegration"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "post": {
        "operationId": "createGitlabIntegration",
        "tags": [
          "GitLab"
        ],
        "summary": "Create GitLab integration",
        "description": "Link a project to a GitLab project. Kaneo generates the secret GitLab must send with each webhook; add the webhook in GitLab afterwards. Use the verify route first to confirm the token really reaches the project.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "baseUrl": {
                    "type": "string",
                    "format": "uri"
                  },
                  "accessToken": {
                    "type": "string",
                    "description": "Omit to keep the stored token only when the GitLab base URL is unchanged. A changed URL requires a new token."
                  },
                  "tokenType": {
                    "type": "string",
                    "enum": [
                      "private",
                      "bearer"
                    ],
                    "description": "`private` sends the token in PRIVATE-TOKEN, which is what personal, project and group access tokens expect. `bearer` sends it in Authorization, for an OAuth2 token you already hold. Defaults to `private`."
                  },
                  "projectPath": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "baseUrl",
                  "projectPath"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The stored integration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GitlabIntegration"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "That GitLab project is already linked to another Kaneo project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "patch": {
        "operationId": "updateGitlabIntegration",
        "tags": [
          "GitLab"
        ],
        "summary": "Update GitLab integration",
        "description": "Update the GitLab 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"
                  },
                  "commentTaskLinkOnGitlabIssue": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated integration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GitlabIntegration"
                }
              }
            }
          },
          "400": {
            "description": "The resulting config failed validation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Integration changed; refresh before updating settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "delete": {
        "operationId": "deleteGitlabIntegration",
        "tags": [
          "GitLab"
        ],
        "summary": "Delete GitLab integration",
        "description": "Unlink a project from its GitLab project.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The integration was removed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GitlabDeleteResult"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or GitLab integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/gitlab-integration/import-issues": {
      "post": {
        "operationId": "importGitlabIssues",
        "tags": [
          "GitLab"
        ],
        "summary": "Import GitLab issues",
        "description": "Import the linked project's open issues as tasks. Issues that already have a task are refreshed rather than duplicated. Requires task:create and task:update permissions.",
        "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/GitlabImportResult"
                }
              }
            }
          },
          "400": {
            "description": "projectId is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:create or task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or webhook integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or webhook integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or Discord integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or Discord integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or Mattermost integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or Mattermost integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or Slack integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or Slack integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or Telegram integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing workspace:manage_settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project or Telegram integration not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Source or target task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "This relation already exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task relation not found, or its source task is gone",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/external-link/task/{taskId}": {
      "post": {
        "operationId": "createExternalLink",
        "tags": [
          "External Links"
        ],
        "summary": "Create an external link",
        "description": "Add a resource link to a task",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "taskId",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "An HTTP or HTTPS URL"
                  },
                  "title": {
                    "type": "string",
                    "maxLength": 200
                  }
                },
                "required": [
                  "url"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "External link created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatedExternalLink"
                }
              }
            }
          },
          "400": {
            "description": "Invalid external link data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No permission to update the task",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "get": {
        "operationId": "getExternalLinksByTask",
        "tags": [
          "External Links"
        ],
        "summary": "Get task external links",
        "description": "Get manually added resource links and links from 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"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/external-link/task/{taskId}/{id}": {
      "delete": {
        "operationId": "deleteExternalLink",
        "tags": [
          "External Links"
        ],
        "summary": "Remove a manual resource link",
        "description": "Remove a manually added link from a task. Integration-managed links cannot be removed through this endpoint.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "taskId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Resource link removed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedExternalLink"
                }
              }
            }
          },
          "400": {
            "description": "Invalid link data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No permission to update the task",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task or manual resource link not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workflow rule not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/workspace": {
      "get": {
        "operationId": "listWorkspaces",
        "tags": [
          "Workspaces"
        ],
        "summary": "List workspaces",
        "description": "List the workspaces where one of the caller's roles grants workspace:read, with the caller's role, sorted by name. Instance admins get every workspace they are a member of, and only those.",
        "responses": {
          "200": {
            "description": "The caller's workspaces",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Workspace"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The API key lacks workspace:read",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/workspace/{workspaceId}": {
      "get": {
        "operationId": "getWorkspace",
        "tags": [
          "Workspaces"
        ],
        "summary": "Get workspace",
        "description": "Get a workspace where one of the caller's roles grants workspace:read, with the caller's role. Instance admins can get any workspace, with a null role when they are not a member.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The workspace",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Workspace"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The API key lacks workspace:read",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found, the caller is not a member of it, or none of their roles grants workspace:read",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/workspace/{workspaceId}/members": {
      "get": {
        "operationId": "getWorkspaceMembers",
        "tags": [
          "Workspaces"
        ],
        "summary": "Get workspace members",
        "description": "Get all members of a workspace, with their role. Pass projectId to get only the members who can access that project.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Only return members who can access this project, for example to fill an assignee picker."
            },
            "required": false,
            "description": "Only return members who can access this project, for example to fill an assignee picker.",
            "name": "projectId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of workspace members",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WorkspaceMember"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found, or project not found in this workspace",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/workspace/{workspaceId}/project-access/me": {
      "get": {
        "operationId": "getMyProjectAccess",
        "tags": [
          "Workspaces"
        ],
        "summary": "Get my project access",
        "description": "Get the caller's own project access in the workspace: every project, or the selected projects they're limited to. Owners and instance admins always get every project.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The caller's project access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemberProjectAccess"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/workspace/{workspaceId}/capabilities": {
      "get": {
        "operationId": "getMyWorkspaceCapabilities",
        "tags": [
          "Workspaces"
        ],
        "summary": "Get my workspace capabilities",
        "description": "Check every named workspace action for the caller in one request: which of them the caller's roles allow, narrowed by the API key's scope when one is used. Instance admins are allowed everything.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The caller's capabilities in the workspace",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkspaceCapabilities"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/workspace/{workspaceId}/project-access": {
      "get": {
        "operationId": "getWorkspaceProjectAccess",
        "tags": [
          "Workspaces"
        ],
        "summary": "Get member project access",
        "description": "List the members who are limited to selected projects, with the projects each one can access. Everyone else in the workspace can access every project. A caller whose own access is limited only sees the projects they can access.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Members limited to selected projects",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MemberProjectAccess"
                  },
                  "description": "Members limited to selected projects. Members not listed can access every project. Project IDs only include projects the caller can access."
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Missing member:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/workspace/{workspaceId}/members/{userId}/project-access": {
      "put": {
        "operationId": "updateMemberProjectAccess",
        "tags": [
          "Workspaces"
        ],
        "summary": "Update member project access",
        "description": "Give a member access to every project, or limit them to selected projects. Owners always access every project, and you can't change your own access or give access to projects you can't access yourself.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "userId",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "projectAccess": {
                    "type": "string",
                    "enum": [
                      "all",
                      "selected"
                    ],
                    "description": "\"all\" gives access to every project in the workspace, including future ones. \"selected\" limits the member to projectIds."
                  },
                  "projectIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "default": [],
                    "description": "Projects the member can access when projectAccess is \"selected\"."
                  }
                },
                "required": [
                  "projectAccess"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The member's project access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemberProjectAccess"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, the member is an owner, or a project is not in this workspace",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Missing member:update permission, changing your own access, or granting a project you can't access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace or member not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing read permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
                      "multiselect"
                    ]
                  },
                  "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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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, or unknown custom field",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing task:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Task not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Custom field not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "put": {
        "operationId": "updateCustomField",
        "tags": [
          "Custom Fields"
        ],
        "summary": "Update custom field",
        "description": "Update a custom field's name, required flag, default, or options. The type can't change, except between dropdown and multiselect. Options that tasks still use can't be removed or renamed; the request is rejected instead of changing task values.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "New name for the field. Cannot be blank."
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "text",
                      "number",
                      "date",
                      "dropdown",
                      "boolean",
                      "multiselect"
                    ],
                    "description": "Only `dropdown` and `multiselect` can switch between each other. Task values are converted, and switching to `dropdown` is rejected while a task has more than one option picked. Any other type change is rejected."
                  },
                  "required": {
                    "type": "boolean",
                    "description": "Whether every task must have a value. Turning it on needs a default, which fills tasks that have no value yet."
                  },
                  "defaultValue": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Value new tasks start with. Send `null` or an empty string to clear it. Multiselect defaults are a JSON array of options."
                  },
                  "options": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "The full option list for dropdown and multiselect fields, in display order. Adding and reordering options is always allowed. Removing or renaming an option that a task still uses is rejected with 400, so task values are never changed silently."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated custom field",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomFieldDefinition"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, a type change, or removing an option that tasks still use",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "No access to the project, or missing project:update permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Custom field not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/import/projects": {
      "post": {
        "operationId": "listImportSourceProjects",
        "tags": [
          "Import"
        ],
        "summary": "List projects in an import source",
        "description": "Sign in to PLANKA, Plane, Linear, Jira, Trello or another Kaneo instance and list the projects that can be imported. The credentials are used only for this request; they are never stored, logged, or returned.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "workspaceId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "connection": {
                    "$ref": "#/components/schemas/ImportConnection"
                  }
                },
                "required": [
                  "workspaceId",
                  "connection"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Projects available in the source",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportSourceProjectList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, credentials the source rejected, or a destination this server may not reach",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "402": {
            "description": "Workspace plan has expired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Missing workspace:manage_settings or project:create permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          },
          "502": {
            "description": "The source could not be reached or answered with an error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/import/runs": {
      "post": {
        "operationId": "startImportRun",
        "tags": [
          "Import"
        ],
        "summary": "Start an import",
        "description": "Import the selected source projects into the workspace as new Kaneo projects. The import runs in the background; poll getImportRun for progress. The credentials are held in memory only while the import runs; they are never stored, logged, or returned. Imported tasks do not send notifications or trigger integrations.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "workspaceId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "connection": {
                    "$ref": "#/components/schemas/ImportConnection"
                  },
                  "projectIds": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 512
                    },
                    "minItems": 1,
                    "maxItems": 50,
                    "description": "Source project IDs from listImportSourceProjects, imported in this order."
                  },
                  "includeComments": {
                    "type": "boolean",
                    "default": true,
                    "description": "Import task comments too. Defaults to true."
                  }
                },
                "required": [
                  "workspaceId",
                  "connection",
                  "projectIds"
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The import started",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportRunEnvelope"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, credentials the source rejected, a destination this server may not reach, or a selected project the source no longer lists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "402": {
            "description": "Workspace plan has expired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Missing workspace:manage_settings or project:create permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Another import is already running in this workspace",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "This server is already running its maximum number of imports, or the API key exceeded its rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "502": {
            "description": "The source could not be reached or answered with an error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "503": {
            "description": "The server is restarting and not starting new imports",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      }
    },
    "/import/runs/{workspaceId}": {
      "get": {
        "operationId": "listImportRuns",
        "tags": [
          "Import"
        ],
        "summary": "List imports",
        "description": "The workspace's 20 most recent imports, newest first. A run whose server stopped reporting progress is returned as failed.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Recent imports",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportRunList"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Missing workspace:manage_settings or project:create permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/import/trello/authorize-url/{workspaceId}": {
      "get": {
        "operationId": "getTrelloAuthorizeUrl",
        "tags": [
          "Import"
        ],
        "summary": "Get the Trello authorize link",
        "description": "Link to Trello's authorize page for this server's Trello app, where the user approves read access and copies a token for startImportRun. null when the server has no TRELLO_API_KEY.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The Trello authorize link",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrelloAuthorizeUrl"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Missing workspace:manage_settings or project:create permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/import/runs/{workspaceId}/{runId}": {
      "get": {
        "operationId": "getImportRun",
        "tags": [
          "Import"
        ],
        "summary": "Get an import",
        "description": "Progress and outcome of one import, including each project's status, counts and warnings.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "runId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The import",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportRunEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "Missing workspace:manage_settings or project:create permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace or import not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/user/me": {
      "get": {
        "operationId": "getCurrentUser",
        "tags": [
          "User"
        ],
        "summary": "Get current user",
        "description": "Return the currently authenticated user.",
        "responses": {
          "200": {
            "description": "Current user",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CurrentUser"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "User not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/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",
                    "maxLength": 64,
                    "description": "One of image/png, image/jpeg, or image/webp.",
                    "example": "image/png"
                  },
                  "data": {
                    "type": "string",
                    "maxLength": 700076,
                    "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": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "408": {
            "description": "Request body timed out",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "413": {
            "description": "Request body exceeds the upload limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "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",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/admin/users": {
      "get": {
        "operationId": "listAdminUsers",
        "tags": [
          "Admin"
        ],
        "summary": "List instance users",
        "description": "Page through every user account on this instance, optionally filtered by a case-insensitive name or email search. Requires an instance administrator session; API keys are rejected.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 200,
              "description": "Case-insensitive match against user name or email."
            },
            "required": false,
            "description": "Case-insensitive match against user name or email.",
            "name": "search",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000000,
              "default": 1
            },
            "required": false,
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Users matching the search",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminUserList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid search, page, or limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The caller is not an instance administrator or is authenticated with an API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/admin/workspaces": {
      "get": {
        "operationId": "listAdminWorkspaces",
        "tags": [
          "Admin"
        ],
        "summary": "List instance workspaces",
        "description": "Page through every workspace on this instance with its owners, member count and project count, optionally filtered by a case-insensitive name or slug search. Requires an instance administrator session; API keys are rejected.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "maxLength": 200,
              "description": "Case-insensitive match against workspace name or slug."
            },
            "required": false,
            "description": "Case-insensitive match against workspace name or slug.",
            "name": "search",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000000,
              "default": 1
            },
            "required": false,
            "name": "page",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Workspaces matching the search",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminWorkspaceList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid search, page, or limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The caller is not an instance administrator or is authenticated with an API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/admin/workspaces/{workspaceId}/members": {
      "get": {
        "operationId": "listAdminWorkspaceMembers",
        "tags": [
          "Admin"
        ],
        "summary": "List workspace members",
        "description": "List every member of a workspace with their role, whether or not the administrator belongs to it.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Workspace members",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AdminWorkspaceMember"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The caller is not an instance administrator or is authenticated with an API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      },
      "post": {
        "operationId": "addAdminWorkspaceMember",
        "tags": [
          "Admin"
        ],
        "summary": "Add a user to a workspace",
        "description": "Add an existing user to a workspace with a role. They start with access to every project. Returns the updated member list.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userId": {
                    "type": "string",
                    "minLength": 1
                  },
                  "role": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100,
                    "description": "A built-in role (viewer, member, admin) or one of the workspace's custom roles. Use the ownership endpoint to make someone the owner."
                  }
                },
                "required": [
                  "userId",
                  "role"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated workspace members",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AdminWorkspaceMember"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unknown role, or the owner role was requested",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The caller is not an instance administrator or is authenticated with an API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace or user not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "The user is already a member",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/admin/workspaces/{workspaceId}/roles": {
      "get": {
        "operationId": "listAdminWorkspaceRoles",
        "tags": [
          "Admin"
        ],
        "summary": "List assignable workspace roles",
        "description": "List the roles an administrator can give members of a workspace: the built-in viewer, member and admin roles plus the workspace's custom roles. Ownership is changed with the ownership transfer instead.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Assignable role names",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Role names an administrator can assign in the workspace."
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The caller is not an instance administrator or is authenticated with an API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/admin/workspaces/{workspaceId}/members/{userId}/role": {
      "put": {
        "operationId": "updateAdminWorkspaceMemberRole",
        "tags": [
          "Admin"
        ],
        "summary": "Change a workspace member's role",
        "description": "Change a member's role. Use the ownership transfer to make someone the owner; the only owner's role can't be changed. Returns the updated member list.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "userId",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "role": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100,
                    "description": "A built-in role (viewer, member, admin) or one of the workspace's custom roles. Use the ownership endpoint to make someone the owner."
                  }
                },
                "required": [
                  "role"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated workspace members",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AdminWorkspaceMember"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unknown role, or the owner role was requested",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The caller is not an instance administrator or is authenticated with an API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace or member not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "The member is the only owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/admin/workspaces/{workspaceId}/members/{userId}": {
      "delete": {
        "operationId": "removeAdminWorkspaceMember",
        "tags": [
          "Admin"
        ],
        "summary": "Remove a workspace member",
        "description": "Remove a member from a workspace. Their account stays. The only owner can't be removed. Returns the updated member list.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "userId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Updated workspace members",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AdminWorkspaceMember"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The caller is not an instance administrator or is authenticated with an API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace or member not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "The member is the only owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    },
    "/admin/workspaces/{workspaceId}/owner": {
      "put": {
        "operationId": "transferAdminWorkspaceOwnership",
        "tags": [
          "Admin"
        ],
        "summary": "Transfer workspace ownership",
        "description": "Make an existing member the only owner of a workspace, for example when the previous owner has left. Previous owners become admins. Returns the updated member list.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "workspaceId",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "userId": {
                    "type": "string",
                    "minLength": 1,
                    "description": "An existing member who becomes the only owner. Previous owners become admins."
                  }
                },
                "required": [
                  "userId"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated workspace members",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/AdminWorkspaceMember"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The member is already the only owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The caller is not an instance administrator or is authenticated with an API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "Workspace or member not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApiKeyRateLimited"
          }
        }
      }
    }
  },
  "webhooks": {}
}
