# GENERATED by docs/api/scripts/build_public_spec.rb from the internal spec (docs/api) and
# docs/api/public/overrides.yaml. Do not edit by hand: change those and run
#   ruby docs/api/scripts/build_public_spec.rb && cp swagger/v1/swagger.yaml ../tarefas-frontend/public/openapi.yaml
openapi: 3.0.3
info:
  title: Lixta API
  version: '2026-10-04'
  description: |
    HTTP API behind [Trama](https://ontrama.com) — workspaces, boards, tasks, milestones, documents and integrations.

    **Base URL:** `https://api.ontrama.com` ·
    **Interactive docs:** [api.ontrama.com/api-docs](https://api.ontrama.com/api-docs) · **Human guide:**
    [ontrama.com/docs](https://ontrama.com/docs) · **MCP (AI agents):** [ontrama.com/mcp](https://ontrama.com/mcp),
    endpoint `https://mcp.ontrama.com/mcp`

    ## Authentication

    Every endpoint except health, login and the OAuth server needs one of:

    1. **JWT** — `Authorization: Bearer <jwt>`, from the e-mail code login (`POST /login`). Valid for 24 hours;
       `POST /logout` invalidates every JWT of the account.
    2. **API key pair** — headers `X-Api-Key` and `X-Api-Secret` (Account → AI / MCP). The secret is shown once, when
       it is generated (`POST /me/api_credentials/regenerate`); store it safely.
    3. **OAuth access token** — `Authorization: Bearer lxt_at_…`, from the OAuth 2.1 flow below. Tokens are scoped and
       only work on the operations that declare the `oauth2` security requirement; any other operation answers
       **403** `{"error":"missing_scope"}`.

    ## OAuth 2.1 (MCP clients)

    Point an MCP client at `https://mcp.ontrama.com/mcp` and it discovers everything: protected-resource metadata on the
    MCP host, authorization-server metadata at `GET /.well-known/oauth-authorization-server`, dynamic client
    registration, authorization code + PKCE (S256) with consent at `https://ontrama.com/oauth2/authorize`, and refresh
    token rotation. Scopes: `boards.read`, `boards.write`, `comments.write`. Access tokens last 7 days.

    ## Conventions

    - Paths work with or without a `.json` suffix (`/boards/41` and `/boards/41.json`).
    - Tasks have a numeric `id` and a stable issue key `PREFIX-123` (unique per workspace). Task routes that take
      `{id}` accept either.
    - Cards are ordered by a fractional `sort_key` string; new and moved cards go to the end of their column unless
      you pass `insert_after_task_id`.
    - Errors: `401` (no or invalid credentials), `403` (your role does not allow it), `404` (not found **or not
      visible to you**), `422` (validation: `{"field": ["message"]}` or `{"error": "…"}`), `429` (rate limited, with
      `Retry-After`).
    - Rate limits: login 30 requests per IP and 10 per e-mail every 15 minutes; OAuth client registration 20 per IP
      per hour; upload presigns 60 per user per hour; invitations (`share`) 30 per user per hour per endpoint.

    ## Access rules

    - You can **see** a board if you are one of its members, an admin of its workspace, a workspace member and the
      board is workspace-visible, or anyone signed in when the board is public (by link — public boards of other
      workspaces are not listed). Everything inside a board you can see is readable.
    - **Editing** a board's content needs a member, admin or owner role on the board (or workspace admin);
      **managing** it (members, sharing, visibility, archive, delete) needs admin or owner (or workspace admin).
    - Workspaces are visible to their members and to users added to one of their boards (the latter see only
      their boards). Workspace admins manage members, settings and integrations.

    ## Realtime

    Board and notification updates are pushed over ActionCable at `wss://api.ontrama.com/cable?token=<jwt>`
    (`BoardChannel` with `board_id`, `NotificationChannel`). Subscriptions to boards you cannot see are rejected.
servers:
- url: https://api.ontrama.com
  description: Production
- url: http://localhost:3000
  description: Local development
security:
- bearerAuth: []
- apiKeyAuth: []
  apiSecretAuth: []
tags:
- name: Health
  description: Liveness probe.
- name: Auth
  description: E-mail code login and logout.
- name: Account
  description: Your profile, avatar upload and the issues assigned to you.
- name: API credentials
  description: Your personal API key pair (also the MCP personal token).
- name: Connected apps
  description: OAuth apps you have authorized.
- name: Notifications
  description: In-app notifications and e-mail preferences.
- name: Search
  description: Full-text search over boards, tasks, comments and documents you can see.
- name: OAuth 2.1
  description: Authorization server for MCP and other OAuth clients.
- name: Workspaces
  description: Workspaces group boards and own the issue prefix.
- name: Workspace members
  description: Workspace roles and invitations.
- name: Workspace documents
  description: Markdown documents inside a workspace.
- name: Workspace activity
  description: Recent activity across the boards of a workspace.
- name: Boards
  description: Boards, the kanban payload, sharing and settings.
- name: Board columns
  description: Columns of a board and bulk actions on their cards.
- name: Board members
  description: Board roles.
- name: Tags
  description: Board labels.
- name: Milestones
  description: Board milestones (timeline).
- name: Tasks
  description: Cards — create, read, update, move, assign, label, time-track, attach.
- name: Checklists
  description: Checklists and checklist items of a task.
- name: Comments
  description: Task comments.
- name: Relations
  description: Relations between tasks (related, blocks / blocked by, duplicate).
- name: Sub-issues
  description: Parent/child hierarchy between tasks.
- name: Pull requests
  description: GitHub pull requests and GitLab merge requests linked to tasks.
- name: Git integrations
  description: GitHub App / GitLab connections of a workspace.
- name: GRUPIM integration
  description: Connect a Discord server (through the GRUPIM bot) to a workspace.
paths:
  "/.well-known/oauth-authorization-server":
    get:
      operationId: oauth_well_known_authorization_server
      tags:
      - OAuth 2.1
      summary: Authorization server metadata (RFC 8414)
      description: OAuth 2.0 authorization server metadata (RFC 8414).
      security: []
      responses:
        '200':
          description: Metadata.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/AuthorizationServerMetadata"
  "/avatar_presign":
    post:
      operationId: users_avatar_presign
      tags:
      - Account
      summary: Presigned S3 POST policy for an avatar upload
      description: |-
        Returns an S3 POST policy for an avatar image (`url` + `fields`; send them with the `file` as multipart form data),
        plus the `public_url` to save with `PUT /me`. Images only, up to 5 MB, valid 15 minutes.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PresignRequest"
            example:
              file_name: me.png
      responses:
        '200':
          description: POST policy, form fields and the resulting public URL.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/PresignedUpload"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              examples:
                missing:
                  value:
                    error: file_name is required
                type:
                  value:
                    error: 'Unsupported file type. Allowed: png, jpg, jpeg, gif, webp'
        '429':
          description: Too many requests. Retry after the time in `Retry-After`.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Too many uploads. Try again later.
  "/boards":
    get:
      operationId: boards_index
      tags:
      - Boards
      summary: List the boards the caller can see
      description: |-
        Boards you can see: boards you are a member of, every board of workspaces you administer, and workspace-visible
        boards of workspaces you belong to. Public boards of other workspaces are only reachable by link. Member e-mails
        are included only on boards you belong to.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      responses:
        '200':
          description: OK.
          content:
            application/json:
              schema:
                type: array
                items:
                  "$ref": "#/components/schemas/BoardListItem"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/MissingScope"
    post:
      operationId: boards_create
      tags:
      - Boards
      summary: Create a board in a workspace
      description: Creates a board in a workspace you administer; you become its owner.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/BoardCreateRequest"
            examples:
              wrapped:
                value:
                  board:
                    name: Lixta roadmap
                    workspace_id: pixta
              webApp:
                value:
                  name: Lixta roadmap
                  workspace_id: pixta
                summary: What the web app sends (top-level, wrapped by ParamsWrapper)
      responses:
        '201':
          description: Board created; body is the (empty) kanban payload.
          headers:
            Location:
              schema:
                type: string
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Board"
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/StatusError-2"
              example:
                status: 400
                error: Bad Request
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
              example:
                user:
                - must be an admin of the workspace to create a board
  "/boards/{board_id}/board_columns":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    post:
      operationId: board_columns_create
      tags:
      - Board columns
      summary: Create a column
      description: Creates a column. Edit rights.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/BoardColumnRequest"
            examples:
              webApp:
                value:
                  name: Unnamed column
                summary: What the web app sends (wrapped by ParamsWrapper)
              wrapped:
                value:
                  board_column:
                    name: In review
                    position: 2
                    color: "#f59e0b"
      responses:
        '201':
          description: Created column.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/BoardColumnDetail"
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/StatusError-2"
              example:
                status: 400
                error: Bad Request
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
  "/boards/{board_id}/board_columns/{id}":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - name: id
      in: path
      required: true
      schema:
        type: integer
      example: 29
    get:
      operationId: board_columns_show
      tags:
      - Board columns
      summary: Get one column with its cards
      description: One column with its open cards.
      responses:
        '200':
          description: Column with its cards.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/BoardColumnDetail"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
    put:
      operationId: board_columns_update
      tags:
      - Board columns
      summary: Rename, recolor or reposition a column
      description: Renames, recolors or repositions a column. Edit rights.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/BoardColumnRequest"
            examples:
              rename:
                value:
                  name: Doing
              recolor:
                value:
                  color: "#f87171"
      responses:
        '200':
          description: Updated column.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/BoardColumnDetail"
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/StatusError-2"
              example:
                status: 400
                error: Bad Request
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Save failed (no validations exist — not expected in practice).
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
    delete:
      operationId: board_columns_destroy
      tags:
      - Board columns
      summary: Delete a column and all of its tasks
      description: >-
        Deletes a column and its cards. If it was the board's to-do, in-review or done column, that setting is cleared. Edit
        rights.
      responses:
        '204':
          "$ref": "#/components/responses/NoContent"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/boards/{board_id}/board_columns/{id}/archive_all_tasks":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - name: id
      in: path
      required: true
      schema:
        type: integer
      example: 31
    put:
      operationId: board_columns_archive_all_tasks
      tags:
      - Board columns
      summary: Archive every task in a column
      description: Archives every card of the column (templates excepted), notifying assignees as for a single archive. Edit
        rights.
      responses:
        '200':
          description: Tasks archived.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    enum:
                    - Tasks archived successfully
                  archived_count:
                    type: integer
              example:
                message: Tasks archived successfully
                archived_count: 12
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/boards/{board_id}/board_columns/{id}/move_all_tasks":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - name: id
      in: path
      required: true
      schema:
        type: integer
      example: 31
    put:
      operationId: board_columns_move_all_tasks
      tags:
      - Board columns
      summary: Move every open task of a column to another column (same or other board)
      description: |-
        Moves every open card of the column (templates excepted) to the end of another column, on this board or another
        board you can edit, keeping their order. Moving to another board keeps comments and history, clears the
        milestone and drops labels. Edit rights on both boards.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/MoveAllTasksRequest"
      responses:
        '200':
          description: Tasks moved.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    enum:
                    - Tasks moved successfully
                  moved_count:
                    type: integer
              example:
                message: Tasks moved successfully
                moved_count: 7
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: 'Missing required parameters: to_board_id and to_column_id'
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              examples:
                source:
                  value:
                    error: Not authorized to edit this board
                target:
                  value:
                    error: Not authorized to edit target board
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/StatusNotFound"
                - "$ref": "#/components/schemas/ErrorMessage"
              examples:
                source:
                  value:
                    status: 404
                    error: Not Found
                targetBoard:
                  value:
                    error: Target board not found or not accessible
                targetColumn:
                  value:
                    error: Target column not found in target board
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    "$ref": "#/components/schemas/ValidationErrors"
              example:
                errors:
                  milestone:
                  - must belong to the same board
        '500':
          description: Server error.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
  "/boards/{board_id}/board_users":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    get:
      operationId: board_users_index
      tags:
      - Board members
      summary: List board members with their roles
      description: Members of the board and their roles.
      responses:
        '200':
          description: Members.
          content:
            application/json:
              schema:
                type: array
                items:
                  "$ref": "#/components/schemas/BoardUser"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Board not found or access denied
  "/boards/{board_id}/board_users/{id}":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - name: id
      in: path
      required: true
      schema:
        type: integer
      example: 88
    put:
      operationId: board_users_update
      tags:
      - Board members
      summary: Change a member's role
      description: >-
        Changes a member's role (`role_viewer`, `role_member`, `role_admin`). Owners and your own role cannot be changed.
        Manage rights.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/BoardUserUpdateRequest"
      responses:
        '200':
          description: Updated membership.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/BoardUser"
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/StatusError-2"
              example:
                status: 400
                error: Bad Request
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: Caller cannot manage the board.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Not authorized to manage board users
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/StatusNotFound"
              examples:
                board:
                  value:
                    error: Board not found or access denied
                membership:
                  value:
                    status: 404
                    error: Not Found
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/ValidationErrors"
              examples:
                owner:
                  value:
                    error: Cannot change owner role
                self:
                  value:
                    error: Cannot change your own role
                role:
                  value:
                    role:
                    - must be one of role_viewer, role_member, role_admin
    delete:
      operationId: board_users_destroy
      tags:
      - Board members
      summary: Remove a member from the board
      description: Removes a member from the board. Owners and yourself cannot be removed. Manage rights.
      responses:
        '200':
          description: Removed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/OkMessage"
              example:
                message: ok
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: Caller cannot manage the board.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Not authorized to manage board users
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/StatusNotFound"
        '422':
          description: Target is the owner or the caller.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              examples:
                owner:
                  value:
                    error: Cannot remove the board owner
                self:
                  value:
                    error: Cannot remove yourself from the board
  "/boards/{board_id}/milestones":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    get:
      operationId: milestones_index
      tags:
      - Milestones
      summary: List the board's milestones
      description: Milestones of the board, in order.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      responses:
        '200':
          description: Milestones.
          content:
            application/json:
              schema:
                type: array
                items:
                  "$ref": "#/components/schemas/Milestone"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
    post:
      operationId: milestones_create
      tags:
      - Milestones
      summary: Create a milestone
      description: Creates a milestone. Edit rights.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/MilestoneRequest"
      responses:
        '201':
          description: Created milestone.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Milestone"
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/StatusError-2"
              example:
                status: 400
                error: Bad Request
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
              example:
                name:
                - can't be blank
  "/boards/{board_id}/milestones/{id}":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - name: id
      in: path
      required: true
      schema:
        type: integer
      example: 3
    get:
      operationId: milestones_show
      tags:
      - Milestones
      summary: Get one milestone
      description: One milestone.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      responses:
        '200':
          description: Milestone.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Milestone"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
    put:
      operationId: milestones_update
      tags:
      - Milestones
      summary: Update a milestone
      description: Updates a milestone. Edit rights.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/MilestoneRequest"
            example:
              milestone:
                name: Beta (public)
                target_date: '2026-12-15T23:59:59.999Z'
                position: 1
      responses:
        '200':
          description: Updated milestone.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Milestone"
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/StatusError-2"
              example:
                status: 400
                error: Bad Request
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
              example:
                position:
                - must be greater than or equal to 0
    delete:
      operationId: milestones_destroy
      tags:
      - Milestones
      summary: Delete a milestone
      description: Deletes a milestone; its cards keep existing without a milestone. Edit rights.
      responses:
        '204':
          "$ref": "#/components/responses/NoContent"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/boards/{board_id}/tags":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    get:
      operationId: tags_index
      tags:
      - Tags
      summary: List the board's tags
      description: Labels of the board.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      responses:
        '200':
          description: Tags of the board.
          content:
            application/json:
              schema:
                type: array
                items:
                  "$ref": "#/components/schemas/TagListItem"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
    post:
      operationId: tags_create
      tags:
      - Tags
      summary: Create a tag
      description: Creates a label. Edit rights.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TagRequest"
            example:
              tag:
                name: backend
                color: "#3b82f6"
                board_id: '41'
      responses:
        '201':
          description: Created tag.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/TagShow"
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/StatusError-2"
              example:
                status: 400
                error: Bad Request
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Save failed (no validations exist — not expected in practice).
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
  "/boards/{board_id}/tags/{id}":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - name: id
      in: path
      required: true
      schema:
        type: integer
      example: 21
    put:
      operationId: tags_update
      tags:
      - Tags
      summary: Rename or recolor a tag
      description: Renames or recolors a label. Edit rights.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TagRequest"
      responses:
        '200':
          description: Updated tag.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/TagShow"
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/StatusError-2"
              example:
                status: 400
                error: Bad Request
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Save failed (no validations exist — not expected in practice).
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
    delete:
      operationId: tags_destroy
      tags:
      - Tags
      summary: Delete a tag (and remove it from every task)
      description: Deletes a label and removes it from every card. Edit rights.
      responses:
        '204':
          "$ref": "#/components/responses/NoContent"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/boards/{board_id}/tasks":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    post:
      operationId: tasks_create
      tags:
      - Tasks
      summary: Create a task (blank or from a template)
      description: |-
        Creates a card, or instantiates a template with `template_id` (copies name, body, priority, labels and
        checklists). The card goes to the end of its column unless `insert_after_task_id` is given. Issue keys mentioned
        in the body are linked as related when you can edit their board. Edit rights.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaskCreateRequest"
            examples:
              blank:
                value:
                  task:
                    board_column_id: 310
                    name: Fix login redirect
                    priority: priority_high
                  insert_after_task_id: 7090
                summary: Blank task after another card (MCP-style)
              fromTemplate:
                value:
                  task:
                    board_column_id: 310
                    sort_key: a3
                    name: Weekly report
                  template_id: 6900
                summary: From a template (web app)
      responses:
        '201':
          description: Created.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
              examples:
                notEditor:
                  value:
                    error: Not authorized to edit this board
                missingScope:
                  value:
                    error: missing_scope
                    error_description: 'Required scope: boards.write'
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/StatusNotFound"
                - "$ref": "#/components/schemas/ErrorMessage"
              examples:
                board:
                  value:
                    status: 404
                    error: Not Found
                template:
                  value:
                    error: Template not found on this board
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/ValidationErrors"
              examples:
                column:
                  value:
                    error: Board column does not belong to this board
                parent:
                  value:
                    parent:
                    - cannot nest more than 8 levels
                dates:
                  value:
                    start_at:
                    - must be on or before due date
                priority:
                  value:
                    priority:
                    - is not included in the list
  "/boards/{board_id}/tasks/picker":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    get:
      operationId: tasks_picker
      tags:
      - Tasks
      summary: Search issues of the workspace (parent / sub-issue / relation picker)
      description: Searches issues of the workspace that you can see (by name or issue key), for parent / sub-issue / relation
        pickers.
      parameters:
      - name: q
        in: query
        required: false
        description: Free text, issue number fragment, or exact issue key.
        schema:
          type: string
        example: BOARDP-1200
      - name: exclude_id
        in: query
        required: false
        description: Task id to leave out (the web app passes the current task).
        schema:
          type: integer
        example: 7104
      responses:
        '200':
          description: Matching issues (0–20).
          content:
            application/json:
              schema:
                type: array
                items:
                  "$ref": "#/components/schemas/PickerItem"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/boards/{board_id}/tasks/{id}":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskIdOrIssueKey"
    get:
      operationId: tasks_show
      tags:
      - Tasks
      summary: Get a task (by id or issue key)
      description: 'A card with everything: assignees, labels, checklists, activity, parent and sub-issues, relations, linked
        PRs.'
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      responses:
        '200':
          description: The task.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/MissingScope"
        '404':
          "$ref": "#/components/responses/NotFound"
    put:
      operationId: tasks_update
      tags:
      - Tasks
      summary: Update a task (fields, column, order, parent)
      description: |-
        Updates card fields (name, body, dates, priority, milestone, template flag, parent, column, order). Changing the
        column without `insert_after_task_id` puts the card at the end. A parent must be on a board you can edit. Edit
        rights.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaskUpdateRequest"
            examples:
              dragAndDrop:
                value:
                  task:
                    sort_key: a0V
                    board_column_id: 311
                summary: Web app drag & drop
              metadata:
                value:
                  task:
                    name: Fix login redirect on Safari
                    due_at:
                    parent_id:
                summary: MCP update_task_metadata
              reposition:
                value:
                  insert_after_task_id: 7090
                  task: {}
                summary: Reposition after a card (server computes sort_key)
      responses:
        '200':
          description: OK.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
              examples:
                notEditor:
                  value:
                    error: Not authorized to edit this board
                missingScope:
                  value:
                    error: missing_scope
                    error_description: 'Required scope: boards.write'
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/ValidationErrors"
              examples:
                column:
                  value:
                    error: Board column does not belong to this board
                cycle:
                  value:
                    parent:
                    - would create a cycle
                milestone:
                  value:
                    milestone:
                    - must belong to the same board
                priority:
                  value:
                    priority:
                    - is not included in the list
    delete:
      operationId: tasks_destroy
      tags:
      - Tasks
      summary: Delete a task
      description: Deletes the card. Edit rights.
      responses:
        '204':
          description: Deleted (no body).
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/boards/{board_id}/tasks/{id}/attachments":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskIdOrIssueKey"
    post:
      operationId: tasks_attachments
      tags:
      - Tasks
      summary: Record an uploaded attachment on the task
      description: Records an uploaded file (its `public_url`) as an attachment of the card. Edit rights.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaskAttachmentRequest"
      responses:
        '201':
          description: Created.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/boards/{board_id}/tasks/{id}/move":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskIdOrIssueKey"
    put:
      operationId: tasks_move
      tags:
      - Tasks
      summary: Move a task to a column of this or another board
      description: |-
        Moves the card to a column of this or another board you can edit (end of the column, or after
        `insert_after_task_id`). Moving to another board keeps comments and history, clears the milestone, drops labels
        and keeps only assignees who can be assigned there. Edit rights on both boards.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaskMoveRequest"
      responses:
        '200':
          description: The moved task (reloaded).
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: 'Missing required parameters: to_board_id and to_column_id'
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
              examples:
                source:
                  value:
                    error: Not authorized to edit this board
                target:
                  value:
                    error: Not authorized to edit target board
                missingScope:
                  value:
                    error: missing_scope
                    error_description: 'Required scope: boards.write'
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/StatusNotFound"
                - "$ref": "#/components/schemas/ErrorMessage"
              examples:
                targetBoard:
                  value:
                    error: Target board not found or not accessible
                targetColumn:
                  value:
                    error: Target column not found in target board
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/TaskMoveInvalid"
        '500':
          description: Server error.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
  "/boards/{board_id}/tasks/{id}/reorder_sub_issues":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - name: id
      in: path
      required: true
      schema:
        type: integer
      example: 7104
    put:
      operationId: sub_issues_reorder
      tags:
      - Sub-issues
      summary: Reorder the children of a task
      description: Reorders the card's children; children not listed keep their places. Edit rights.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SubIssuesReorderRequest"
      responses:
        '200':
          description: OK.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Ids duplicated or not all direct children.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: All issues must be sub-issues of this parent
  "/boards/{board_id}/tasks/{id}/stopwatch":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskIdOrIssueKey"
    put:
      operationId: tasks_stopwatch
      tags:
      - Tasks
      summary: Start or stop the task stopwatch
      description: Starts or stops the card's time tracker. Edit rights.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      responses:
        '200':
          description: The task with updated timer fields.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/boards/{board_id}/tasks/{id}/taggings":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskIdOrIssueKey"
    put:
      operationId: tasks_taggings
      tags:
      - Tasks
      summary: Replace the task's labels
      description: Replaces the card's labels with `tag_ids` (labels of this board only). Edit rights.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaskTaggingsRequest"
      responses:
        '200':
          description: OK.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
              examples:
                notEditor:
                  value:
                    error: Not authorized to edit this board
                missingScope:
                  value:
                    error: missing_scope
                    error_description: 'Required scope: boards.write'
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: A tag id that is not a tag of this board.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Tag 99 does not belong to this board
  "/boards/{board_id}/tasks/{id}/task_users":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskIdOrIssueKey"
    put:
      operationId: tasks_task_users
      tags:
      - Tasks
      summary: Replace the task's assignees
      description: |-
        Replaces the card's assignees with `user_ids`; only added people are notified. Assignees must be board members,
        workspace admins, or workspace members on a workspace-visible board. Edit rights.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaskUsersRequest"
      responses:
        '200':
          description: OK.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
              examples:
                notEditor:
                  value:
                    error: Not authorized to edit this board
                missingScope:
                  value:
                    error: missing_scope
                    error_description: 'Required scope: boards.write'
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              examples:
                notArray:
                  value:
                    error: user_id must be an array
                notMember:
                  value:
                    error: User 265 is not a member of the board
  "/boards/{board_id}/tasks/{id}/upload_presign":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskIdOrIssueKey"
    post:
      operationId: tasks_upload_presign
      tags:
      - Tasks
      summary: Get a presigned S3 POST policy to upload a task attachment
      description: |-
        Returns an S3 POST policy for an attachment (`url` + `fields`; send them with the `file` as multipart form data)
        and the `public_url` to record with `POST …/attachments`. Images and documents up to 25 MB, valid 15 minutes.
        Edit rights.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PresignRequest"
      responses:
        '200':
          description: POST policy, form fields and the public URL of the future object.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/PresignedUpload"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: file_name is required
        '429':
          description: Too many requests. Retry after the time in `Retry-After`.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
  "/boards/{board_id}/tasks/{task_id}/comments":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskId"
    post:
      operationId: comments_create
      tags:
      - Comments
      summary: Comment on a task
      description: |-
        Adds a comment. `@mentions` notify board members (and workspace members on workspace-visible boards); issue keys
        in the text are linked as related when you can edit their board. Edit rights.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - comments.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CommentCreateRequest"
      responses:
        '201':
          description: Created.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
              examples:
                notEditor:
                  value:
                    error: Not authorized to edit this board
                missingScope:
                  value:
                    error: missing_scope
                    error_description: 'Required scope: comments.write'
        '404':
          "$ref": "#/components/responses/NotFound"
  "/boards/{board_id}/tasks/{task_id}/comments/{id}":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskId"
    - name: id
      in: path
      required: true
      schema:
        type: integer
      example: 88123
    put:
      operationId: comments_update
      tags:
      - Comments
      summary: Edit a comment
      description: Edits your comment on a task; returns the task.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - comments.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - body
              properties:
                body:
                  type: string
      responses:
        '200':
          description: The task after the edit.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: array
                  items:
                    type: string
    patch:
      operationId: comments_patch
      tags:
      - Comments
      summary: Edit a comment (PATCH)
      description: Edits your comment on a task; returns the task.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - comments.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - body
              properties:
                body:
                  type: string
      responses:
        '200':
          description: The task after the edit.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
        '404':
          "$ref": "#/components/responses/NotFound"
    delete:
      operationId: comments_destroy
      tags:
      - Comments
      summary: Delete a comment
      description: Deletes a comment — your own, or any comment if you can manage the board. Returns the updated card.
      responses:
        '200':
          description: The task after the deletion.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              examples:
                notEditor:
                  value:
                    error: Not authorized to edit this board
                notAuthor:
                  value:
                    error: Not authorized to delete this comment
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/StatusNotFound"
  "/boards/{board_id}/tasks/{task_id}/pull_requests":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskId"
    post:
      operationId: task_pull_requests_create
      tags:
      - Pull requests
      summary: Link a PR/MR to a task
      description: Links a GitHub pull request or GitLab merge request by URL. The same PR can be linked to several cards.
        Edit rights.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PullRequestLinkRequest"
            examples:
              byUrl:
                value:
                  url: https://github.com/locomotiva/tarefas-backend/pull/42
                summary: Web app (paste URL)
              byTriple:
                value:
                  provider: gitlab
                  repository: locomotiva/tarefas
                  number: 7
                  title: Fix login redirect
                  status: draft
                summary: Explicit provider / repository / number
      responses:
        '201':
          description: Created.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/ErrorList"
              examples:
                unsupportedUrl:
                  value:
                    error: Unsupported PR/MR URL. Use github.com or gitlab.com.
                invalid:
                  value:
                    errors:
                    - Provider is not included in the list
  "/boards/{board_id}/tasks/{task_id}/pull_requests/{id}":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskId"
    - name: id
      in: path
      required: true
      schema:
        type: integer
      example: 318
    delete:
      operationId: task_pull_requests_destroy
      tags:
      - Pull requests
      summary: Unlink a PR/MR from a task
      description: Unlinks a pull request from the card. Edit rights.
      responses:
        '200':
          description: OK.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/boards/{board_id}/tasks/{task_id}/relations":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskId"
    post:
      operationId: task_relations_create
      tags:
      - Relations
      summary: Relate the task to another issue
      description: |-
        Relates the card to another issue (by id or issue key): `related`, `blocks`, `blocked_by` or `duplicate`. The
        other issue must be on a board you can edit (404 if you cannot see it). Edit rights.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaskRelationCreateRequest"
      responses:
        '201':
          description: Created.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
              examples:
                notEditor:
                  value:
                    error: Not authorized to edit this board
                missingScope:
                  value:
                    error: missing_scope
                    error_description: 'Required scope: boards.write'
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/StatusNotFound"
                - "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Related issue not found or not accessible
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/TaskErrorList"
              examples:
                unknownType:
                  value:
                    error: 'Unknown relation type: parent'
                notEditable:
                  value:
                    error: Not authorized to modify the related issue
                invalid:
                  value:
                    errors:
                    - issues cannot block each other
                duplicate:
                  value:
                    error: Relation already exists
  "/boards/{board_id}/tasks/{task_id}/relations/{id}":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskId"
    - name: id
      in: path
      required: true
      schema:
        type: integer
      example: 431
    delete:
      operationId: task_relations_destroy
      tags:
      - Relations
      summary: Remove a relation
      description: Removes a relation of the card. Edit rights.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      responses:
        '200':
          description: OK.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
              examples:
                notEditor:
                  value:
                    error: Not authorized to edit this board
                missingScope:
                  value:
                    error: missing_scope
                    error_description: 'Required scope: boards.write'
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/StatusNotFound"
                - "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Relation not found
  "/boards/{board_id}/tasks/{task_id}/sub_issues":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskId"
    post:
      operationId: sub_issues_create
      tags:
      - Sub-issues
      summary: Create children or attach existing issues as children
      description: Creates new child issues and/or attaches existing ones (by id or issue key, on boards you can edit). Edit
        rights.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SubIssuesCreateRequest"
            examples:
              create:
                value:
                  names:
                  - Write migration
                  - Backfill data
                summary: Create from a pasted list (web app)
              attach:
                value:
                  existing_task_id: 7120
                summary: Attach an existing issue (web app)
      responses:
        '201':
          description: Created.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Task"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/ValidationErrors"
              examples:
                noName:
                  value:
                    error: Name is required
                notAccessible:
                  value:
                    error: Issue not found or not accessible
                notEditable:
                  value:
                    error: Not authorized to modify the related issue
                cycle:
                  value:
                    parent:
                    - would create a cycle
  "/boards/{board_id}/tasks/{task_id}/task_check_items":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskId"
    post:
      operationId: task_check_items_create
      tags:
      - Checklists
      summary: Add an item to a checklist
      description: Adds an item to a checklist of the card. Edit rights.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaskCheckItemRequest"
      responses:
        '201':
          description: The item record.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/TaskCheckItemRecord"
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/BadRequest"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/boards/{board_id}/tasks/{task_id}/task_check_items/{id}":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskId"
    - "$ref": "#/components/parameters/Id"
    put:
      operationId: task_check_items_update
      tags:
      - Checklists
      summary: Toggle / rename or delete a checklist item
      description: 'Checks, renames or moves an item between the card''s checklists, or deletes it with `_destroy: true`.
        Edit rights.'
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaskCheckItemRequest"
            examples:
              toggle:
                value:
                  task_check_item:
                    id: 5521
                    is_complete: true
                summary: Toggle (web app)
              destroy:
                value:
                  task_check_item:
                    id: 5521
                    _destroy: true
                summary: Delete (web app)
      responses:
        '200':
          description: Updated item record.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/TaskCheckItemRecord"
        '204':
          description: No content.
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/BadRequest"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/ValidationErrors"
              example:
                error: Checklist does not belong to this task
    delete:
      operationId: task_check_items_destroy
      tags:
      - Checklists
      summary: Delete a checklist item
      description: Deletes a checklist item. Edit rights.
      responses:
        '204':
          description: Deleted.
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/boards/{board_id}/tasks/{task_id}/task_checklists":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskId"
    post:
      operationId: task_checklists_create
      tags:
      - Checklists
      summary: Add a checklist to a task
      description: Adds a checklist. Edit rights.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaskChecklistRequest"
            examples:
              webApp:
                value:
                  name: New Checklist
                summary: Web app (top-level, wrapped by ParamsWrapper)
              explicit:
                value:
                  task_checklist:
                    name: QA
                    position: 1
                summary: Explicit wrapper
      responses:
        '201':
          description: The checklist record.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/TaskChecklistRecord"
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/BadRequest"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/boards/{board_id}/tasks/{task_id}/task_checklists/{id}":
    parameters:
    - "$ref": "#/components/parameters/BoardId"
    - "$ref": "#/components/parameters/TaskId"
    - "$ref": "#/components/parameters/Id"
    put:
      operationId: task_checklists_update
      tags:
      - Checklists
      summary: Rename / reposition or delete a checklist
      description: 'Renames or repositions a checklist, or deletes it with `_destroy: true`. Edit rights.'
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaskChecklistRequest"
            examples:
              rename:
                value:
                  id: 912
                  name: Release checklist
                summary: Rename (web app)
              destroy:
                value:
                  id: 912
                  _destroy: true
                summary: Delete (web app)
      responses:
        '200':
          description: Updated checklist record.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/TaskChecklistRecord"
        '204':
          description: No content.
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/BadRequest"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
    delete:
      operationId: task_checklists_destroy
      tags:
      - Checklists
      summary: Delete a checklist
      description: Deletes a checklist and its items. Edit rights.
      responses:
        '204':
          description: Deleted.
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/boards/{id}":
    parameters:
    - "$ref": "#/components/parameters/BoardIdAsId"
    get:
      operationId: boards_show
      tags:
      - Boards
      summary: Get the kanban payload of a board
      description: |-
        The full kanban payload: columns with their cards (assignees, labels, checklists, activity, relations, linked PRs),
        templates and milestones. Archived cards are included with `show_archived=true`.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      parameters:
      - name: show_archived
        in: query
        required: false
        schema:
          type: string
        example: 'true'
      responses:
        '200':
          description: Kanban payload.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Board"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
              examples:
                cannotView:
                  value:
                    error: Not authorized to view this board
                missingScope:
                  value:
                    error: missing_scope
                    error_description: 'Required scope: boards.read'
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Board not found or access denied
    put:
      operationId: boards_update
      tags:
      - Boards
      summary: Update board settings
      description: >-
        Updates name, description, settings and the to-do / in-review / done columns (edit rights). Changing visibility needs
        manage rights.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/BoardUpdateRequest"
            examples:
              settings:
                value:
                  board:
                    time_tracking_enabled: true
                    description: Product roadmap
                    todo_board_column_id: 28
                    done_board_column_id: 31
                    in_review_board_column_id:
                summary: Settings modal
              visibility:
                value:
                  board:
                    visibility: visibility_workspace
                summary: Share modal
              rename:
                value:
                  name: Lixta roadmap 2027
                  id: 41
                summary: Header rename (top-level, wrapped by ParamsWrapper)
      responses:
        '200':
          description: Updated board (kanban payload, archived cards excluded).
          headers:
            Location:
              schema:
                type: string
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Board"
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/StatusError-2"
              example:
                status: 400
                error: Bad Request
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              examples:
                edit:
                  value:
                    error: Not authorized to edit this board
                visibility:
                  value:
                    error: Not authorized to manage this board
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Board not found or access denied
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
              examples:
                foreignColumn:
                  value:
                    base:
                    - Column with id 999 does not belong to this board
                unknownVisibility:
                  value:
                    visibility:
                    - is not included in the list
    delete:
      operationId: boards_destroy
      tags:
      - Boards
      summary: Delete a board and everything in it
      description: Deletes the board and everything in it. Manage rights.
      responses:
        '204':
          "$ref": "#/components/responses/NoContent"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Not authorized to delete this board
        '404':
          "$ref": "#/components/responses/NotFound"
  "/boards/{id}/archive":
    parameters:
    - "$ref": "#/components/parameters/BoardIdAsId"
    put:
      operationId: boards_archive
      tags:
      - Boards
      summary: Archive or unarchive the board
      description: 'Archives (`archived: true`) or unarchives (`false`) the board; without the parameter it toggles. Manage
        rights.'
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                archived:
                  type: boolean
            example:
              archived: true
      responses:
        '200':
          description: Board after the update.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Board"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardManage"
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Board not found or access denied
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
              examples:
                notBoolean:
                  value:
                    archived:
                    - must be true or false
                invalidBoard:
                  value:
                    base:
                    - Column with id 999 does not belong to this board
  "/boards/{id}/share":
    parameters:
    - "$ref": "#/components/parameters/BoardIdAsId"
    post:
      operationId: boards_share
      tags:
      - Boards
      summary: Invite a user (by e-mail) to the board
      description: |-
        Invites someone by e-mail (an account is created if needed); their board role follows their workspace role.
        Existing members are not changed or e-mailed again. Manage rights. Invalid e-mail → 422; throttled (429).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ShareRequest"
      responses:
        '200':
          description: OK.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Board"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardManage"
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Board not found or access denied
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
              examples:
                blank:
                  value:
                    email:
                    - can't be blank
                invalid:
                  value:
                    email:
                    - is invalid
        '429':
          description: Too many requests. Retry after the time in `Retry-After`.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Too many invitations, try again later
  "/boards/{id}/update_columns_positions":
    parameters:
    - "$ref": "#/components/parameters/BoardIdAsId"
    put:
      operationId: boards_update_columns_positions
      tags:
      - Boards
      summary: Reorder the board's columns
      description: Reorders columns. `positions` is a list of `{id, position}` integers for this board's columns. Edit rights.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PositionsRequest"
            example:
              positions:
              - id: 28
                position: 0
              - id: 31
                position: 1
              - id: 29
                position: 2
      responses:
        '200':
          description: Positions written.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/OkMessage"
              example:
                message: ok
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenBoardEdit"
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Board not found or access denied
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: positions must be a list of {id, position} integers
  "/login":
    post:
      operationId: users_login
      tags:
      - Auth
      summary: Request an OTP e-mail, or exchange the OTP for a JWT
      description: |-
        Two steps on the same endpoint. Send `{"email"}` to receive a 6-digit code by e-mail (answers **400** — that is
        the expected "code sent" response; unknown e-mails get an account). Then send `{"email", "otp"}` to get a JWT
        (**201**). Codes are valid for 10 minutes and can be used once; after 5 wrong codes the code is locked and a new
        one must be requested (**403**). Invalid e-mail → 422. Throttled per IP and per e-mail (429).
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/LoginRequest"
            examples:
              requestCode:
                value:
                  email: you@example.com
                summary: Step 1 — ask for a code
              exchangeCode:
                value:
                  email: you@example.com
                  otp: '482193'
                summary: Step 2 — exchange the code
      responses:
        '201':
          description: OTP accepted; JWT issued.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/LoginResponse"
              example:
                user:
                  id: 12
                  email: you@example.com
                  name: João Netto
                  avatar_url:
                  cellphone:
                  created_at: '2025-03-01T10:00:00.000-03:00'
                  updated_at: '2026-10-04T09:00:00.000-03:00'
                token: eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEyLCJleHAiOjE3NTk2MjI0MDB9.Zx1…
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/LoginOtpSent"
              examples:
                newUser:
                  value: {}
                  summary: E-mail not registered — user created
                existingUser:
                  value:
                    job_id: 0b8e5c3e-7d0a-4a52-9f8e-2f4b1c6d9a10
                  summary: Existing user, code requested
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Code expired or too many wrong attempts. Request a new code.
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Invalid e-mail address
        '429':
          description: Too many requests. Retry after the time in `Retry-After`.
          headers:
            Retry-After:
              schema:
                type: integer
                example: 900
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Too many login attempts. Try again later.
  "/logout":
    post:
      operationId: users_logout
      tags:
      - Auth
      summary: Invalidate every JWT of the user issued so far
      description: Invalidates every JWT issued to your account so far (all devices). API keys keep working.
      responses:
        '204':
          "$ref": "#/components/responses/NoContent"
        '401':
          "$ref": "#/components/responses/Unauthorized"
  "/me":
    get:
      operationId: users_me
      tags:
      - Account
      summary: Current user
      description: Your profile.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      responses:
        '200':
          description: The signed-in user.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/User"
              example:
                id: 12
                email: you@example.com
                name: João Netto
                avatar_url: https://s3.sa-east-1.amazonaws.com/lixtame-public/uploads/me_3f9a1c2b.png
                cellphone:
                created_at: '2025-03-01T10:00:00.000-03:00'
                updated_at: '2026-10-04T09:00:00.000-03:00'
        '401':
          "$ref": "#/components/responses/Unauthorized"
    put:
      operationId: users_update
      tags:
      - Account
      summary: Update the current user
      description: Update your name, username, phone or avatar URL. The e-mail cannot be changed here.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/UserUpdateRequest"
      responses:
        '200':
          description: Updated user.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/User"
        '400':
          description: Missing or malformed parameters.
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '422':
          description: |-
            Validation failed. No permitted attribute is validated today, so this only happens for a legacy row that is
            invalid for another reason.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
  "/me/api_credentials":
    get:
      operationId: api_credentials_show
      tags:
      - API credentials
      summary: Show the personal API key and MCP URL (the secret is never shown again)
      description: >-
        Your API key and the MCP URL. The secret and the personal token are never returned here — they are shown once, by
        `regenerate`.
      responses:
        '200':
          description: Current credentials, without the secret.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ApiCredentials"
              example:
                api_key: 9f2c4e1a7b3d5f60a1b2c3d4e5f60718
                api_secret:
                token:
                mcp_url: https://mcp.ontrama.com/mcp
                reset_at: '2026-09-12T14:03:11.000-03:00'
        '401':
          "$ref": "#/components/responses/Unauthorized"
  "/me/api_credentials/regenerate":
    post:
      operationId: api_credentials_regenerate
      tags:
      - API credentials
      summary: Rotate the API key pair
      description: |-
        Creates a new key pair and returns it, with the personal MCP token `<api_key>.<api_secret>`. This is the only time
        the secret is shown. The previous pair stops working immediately.
      responses:
        '200':
          description: The new credentials, secret and MCP personal token included (shown once).
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ApiCredentials"
              example:
                api_key: 9f2c4e1a7b3d5f60a1b2c3d4e5f60718
                api_secret: 0a1b2c3d4e5f60718293a4b5c6d7e8f9
                token: 9f2c4e1a7b3d5f60a1b2c3d4e5f60718.0a1b2c3d4e5f60718293a4b5c6d7e8f9
                mcp_url: https://mcp.ontrama.com/mcp
                reset_at: '2026-10-04T14:03:11.000-03:00'
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '422':
          description: Validation failed.
  "/me/oauth_clients":
    get:
      operationId: oauth_clients_index
      tags:
      - Connected apps
      summary: List OAuth apps the user has authorized
      description: OAuth apps you have authorized, with their scopes and last use.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2: []
      responses:
        '200':
          description: Connected apps.
          content:
            application/json:
              schema:
                type: array
                items:
                  "$ref": "#/components/schemas/ConnectedApp"
              example:
              - id: 3
                client_id: 4a6f0d7e-2c55-4f0b-9a63-0a8e3c7b1f20
                client_name: Claude
                scopes:
                - boards.read
                - boards.write
                - comments.write
                resource: https://mcp.ontrama.com/mcp
                created_at: '2026-10-01T18:22:04.000-03:00'
                last_used_at: '2026-10-04T08:51:30.000-03:00'
                expires_at: '2026-10-08T18:22:04.000-03:00'
        '401':
          "$ref": "#/components/responses/Unauthorized"
  "/me/oauth_clients/{id}":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        oneOf:
        - type: integer
        - type: string
          format: uuid
      example: 3
    delete:
      operationId: oauth_clients_destroy
      tags:
      - Connected apps
      summary: Disconnect an OAuth app
      description: Disconnects an OAuth app (by `client_id`) and revokes all its tokens.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2: []
      responses:
        '204':
          "$ref": "#/components/responses/NoContent"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/OAuthError"
              example:
                error: not_found
                error_description: Client not found
  "/me/tasks":
    get:
      operationId: assigned_tasks_index
      tags:
      - Account
      summary: My open issues across all boards
      description: Open issues assigned to you across all your boards.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      responses:
        '200':
          description: Assigned, open tasks.
          content:
            application/json:
              schema:
                type: array
                items:
                  "$ref": "#/components/schemas/AssignedTask"
              example:
              - id: 7104
                name: Fix login redirect
                priority: priority_high
                due_at: '2026-10-06T18:00:00.000-03:00'
                board_column_id: 210
                board_id: 41
                sort_key: a0V
                issue_number: 1377
                parent_id:
                issue_key: BOARDP-1377
                tags:
                - id: 88
                  board_id: 41
                  user_id: 12
                  name: bug
                  color: "#ef4444"
                  lower_tag: bug
                  created_at: '2025-05-02T10:00:00.000-03:00'
                  updated_at: '2025-05-02T10:00:00.000-03:00'
                parent_issue_key:
                sub_issues_progress:
                  completed: 1
                  total: 3
                blocked: false
                blocks_count: 1
                is_done: false
                pull_requests:
                - id: 15
                  provider: github
                  number: 42
                  url: https://github.com/lixta/tarefas-backend/pull/42
                  title: BOARDP-1377 fix login redirect
                  status: open
                  review_state: pending
                  ci_status: success
                  display_ref: "#42"
                board:
                  id: 41
                  name: Lixta backlog
                  workspace_id: 3
                column:
                  id: 210
                  name: Doing
        '401':
          "$ref": "#/components/responses/Unauthorized"
  "/notification_preferences":
    get:
      operationId: notification_preferences_show
      tags:
      - Notifications
      summary: Get e-mail notification preferences
      description: Your e-mail notification preferences.
      responses:
        '200':
          description: Preferences.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/NotificationPreferences"
        '401':
          "$ref": "#/components/responses/Unauthorized"
    put:
      operationId: notification_preferences_update
      tags:
      - Notifications
      summary: Update e-mail notification preferences
      description: Turn e-mail notifications on or off, globally or per notification type.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/NotificationPreferencesUpdateRequest"
      responses:
        '200':
          description: Updated preferences.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/NotificationPreferences"
        '400':
          description: Missing or malformed parameters.
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '422':
          description: Validation failed.
        '500':
          description: Server error.
  "/notifications":
    get:
      operationId: notifications_index
      tags:
      - Notifications
      summary: List the user's notifications
      description: Your notifications, newest first (`limit` up to 100, default 50; `offset`).
      parameters:
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          default: 50
          maximum: 100
      - name: offset
        in: query
        required: false
        schema:
          type: integer
          default: 0
      responses:
        '200':
          description: Notifications, newest first.
          content:
            application/json:
              schema:
                type: array
                items:
                  "$ref": "#/components/schemas/Notification"
        '401':
          "$ref": "#/components/responses/Unauthorized"
  "/notifications/mark_all_read":
    put:
      operationId: notifications_mark_all_read
      tags:
      - Notifications
      summary: Mark every unread notification as read
      description: Marks all your notifications as read.
      responses:
        '200':
          description: Done.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/NotificationsMarkAllRead"
        '401':
          "$ref": "#/components/responses/Unauthorized"
  "/notifications/unread_count":
    get:
      operationId: notifications_unread_count
      tags:
      - Notifications
      summary: Number of unread notifications
      description: Number of unread notifications.
      responses:
        '200':
          description: Unread count.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/NotificationsUnreadCount"
        '401':
          "$ref": "#/components/responses/Unauthorized"
  "/notifications/{id}":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: integer
      example: 5512
    put:
      operationId: notifications_update
      tags:
      - Notifications
      summary: Mark one notification as read
      description: Marks a notification as read (idempotent).
      responses:
        '200':
          description: The notification, read (now or earlier).
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Notification"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/oauth2/authorize":
    get:
      operationId: oauth2_preview
      tags:
      - OAuth 2.1
      summary: Preview an authorization request (consent page data)
      description: >-
        Validates an authorization request and returns what the consent page shows (client, scopes, redirect URI). No authentication.
      security: []
      parameters:
      - name: client_id
        in: query
        required: true
        schema:
          type: string
          format: uuid
      - name: scope
        in: query
        required: false
        description: >-
          Space/comma-separated scopes; unknown ones and those the client did not register are dropped; empty → the client's
          registered scopes.
        schema:
          type: string
        example: boards.read boards.write
      - name: response_type
        in: query
        required: false
        schema:
          type: string
          default: code
      - name: redirect_uri
        in: query
        required: false
        schema:
          type: string
      - name: state
        in: query
        required: false
        schema:
          type: string
      - name: resource
        in: query
        required: false
        schema:
          type: string
        example: https://mcp.ontrama.com/mcp
      responses:
        '200':
          description: Data for the consent page.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/AuthorizePreview"
        '401':
          description: Missing or invalid credentials.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/OAuthError"
              example:
                error: invalid_client
                error_description: Unknown client_id
    post:
      operationId: oauth2_authorize
      tags:
      - OAuth 2.1
      summary: Approve an authorization request and issue a code
      description: |-
        Approves an authorization request on behalf of the signed-in user and returns the redirect URL with the code.
        Only a web session (JWT) can approve; API keys and OAuth tokens get 403 `access_denied`. Scopes are capped by the
        client's registered scope. PKCE S256 is required.
      security:
      - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/AuthorizeRequest"
      responses:
        '200':
          description: OK.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/AuthorizeResponse"
        '400':
          description: Invalid request (see the table above).
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/OAuthError"
              examples:
                notRegistered:
                  value:
                    error: invalid_request
                    error_description: redirect_uri is not registered
                noPkce:
                  value:
                    error: invalid_request
                    error_description: code_challenge is required for public clients
                responseType:
                  value:
                    error: unsupported_response_type
                    error_description: Only response_type=code is supported
                scopeNotRegistered:
                  value:
                    error: invalid_scope
                    error_description: None of the requested scopes is allowed for this client
        '401':
          description: Missing or invalid credentials.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/OAuthError"
              examples:
                notSignedIn:
                  value:
                    error: User authentication failed
                unknownClient:
                  value:
                    error: invalid_client
                    error_description: Unknown client_id
        '403':
          description: Authenticated with an OAuth access token or the API key pair instead of a JWT.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/OAuthError"
              example:
                error: access_denied
                error_description: Authorization requires a signed-in Lixta session; OAuth tokens and API keys are not accepted
  "/oauth2/register":
    post:
      operationId: oauth2_register
      tags:
      - OAuth 2.1
      summary: Dynamic client registration (RFC 7591)
      description: |-
        Dynamic client registration (RFC 7591) for public clients (`token_endpoint_auth_method: none`). Redirect URIs must
        be HTTPS or loopback. Rate limited per IP.
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/OAuthClientRegistrationRequest"
          application/x-www-form-urlencoded:
            schema:
              "$ref": "#/components/schemas/OAuthClientRegistrationRequest"
      responses:
        '201':
          description: Client registered.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/OAuthClientRegistration"
        '400':
          description: Invalid metadata.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/OAuthError"
              examples:
                authMethod:
                  value:
                    error: invalid_client_metadata
                    error_description: Unsupported token_endpoint_auth_method
                redirectUri:
                  value:
                    error: invalid_redirect_uri
                    error_description: One or more redirect_uris are invalid
  "/oauth2/revoke":
    post:
      operationId: oauth2_revoke
      tags:
      - OAuth 2.1
      summary: Revoke an access or refresh token (RFC 7009)
      description: Revokes an access or refresh token (RFC 7009).
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/RevokeRequest"
          application/x-www-form-urlencoded:
            schema:
              "$ref": "#/components/schemas/RevokeRequest"
      responses:
        '200':
          description: Revoked, or nothing to revoke. Empty body.
        '401':
          description: Missing or invalid credentials.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/OAuthError"
              example:
                error: invalid_client
                error_description: client_id is required
  "/oauth2/token":
    post:
      operationId: oauth2_token
      tags:
      - OAuth 2.1
      summary: Exchange an authorization code or a refresh token for tokens
      description: |-
        `grant_type=authorization_code` (with `code_verifier`) or `grant_type=refresh_token`. Refresh tokens rotate: each
        one can be used once. Responses are not cacheable.
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TokenRequest"
            examples:
              authorizationCode:
                value:
                  grant_type: authorization_code
                  client_id: 4a6f0d7e-2c55-4f0b-9a63-0a8e3c7b1f20
                  code: ac_Q2xhdWRlIGlzIGEgZ29vZCBjb2RlIGZvciB0aGlzIGV4YW1wbGU
                  redirect_uri: https://claude.ai/api/mcp/auth_callback
                  code_verifier: dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
                  resource: https://mcp.ontrama.com/mcp
              refreshToken:
                value:
                  grant_type: refresh_token
                  client_id: 4a6f0d7e-2c55-4f0b-9a63-0a8e3c7b1f20
                  refresh_token: lxt_rt_9KfJ2mWq7Lx0aP3vR8sT1yU6bN4cD5eG2hI0jK7lM3n
          application/x-www-form-urlencoded:
            schema:
              "$ref": "#/components/schemas/TokenRequest"
      responses:
        '200':
          description: New token pair.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/TokenResponse"
              example:
                access_token: lxt_at_Vt3x0kq1yR8w2-JmX5dQeN7cP4uL9aZbH6sGf0TiWoE
                token_type: Bearer
                expires_in: 604800
                refresh_token: lxt_rt_9KfJ2mWq7Lx0aP3vR8sT1yU6bN4cD5eG2hI0jK7lM3n
                scope: boards.read boards.write comments.write
                resource: https://mcp.ontrama.com/mcp
        '400':
          description: Invalid grant or request (see the tables above).
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/OAuthError"
              examples:
                invalidCode:
                  value:
                    error: invalid_grant
                    error_description: Invalid authorization code
                badVerifier:
                  value:
                    error: invalid_grant
                    error_description: Invalid code_verifier
                reuse:
                  value:
                    error: invalid_grant
                    error_description: Refresh token reuse detected
                grantType:
                  value:
                    error: unsupported_grant_type
                    error_description: 'Supported: authorization_code, refresh_token'
        '401':
          description: Missing or invalid credentials.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/OAuthError"
              example:
                error: invalid_client
                error_description: Unknown client_id
  "/public/documents/{public_token}":
    parameters:
    - name: public_token
      in: path
      required: true
      description: The token set when the document was first published.
      schema:
        type: string
    get:
      operationId: public_documents_show
      tags:
      - Workspace documents
      summary: Read a published document
      description: A published page (title, icon, Markdown body). No authentication.
      security: []
      responses:
        '200':
          description: The published page.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/PublicDocument"
        '404':
          description: Not published, archived, or unknown.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
  "/search":
    get:
      operationId: search_search
      tags:
      - Search
      summary: Full-text search over boards, tasks and comments
      description: |-
        Full-text search (word prefixes, any word) over boards, tasks, comments and documents you can see. Pass `board_id`
        to limit tasks and comments to one board. At most 50 results, best match first. Document results carry
        `workspace_document` (id, title, icon, workspace slug and name).
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      parameters:
      - name: q
        in: query
        required: false
        description: Search text. Not required by the code; blank → empty array.
        schema:
          type: string
        example: login redirect
      - name: board_id
        in: query
        required: false
        schema:
          type: integer
        example: 41
      responses:
        '200':
          description: Matching documents, best rank first (at most 50).
          content:
            application/json:
              schema:
                type: array
                maxItems: 50
                items:
                  "$ref": "#/components/schemas/SearchResult"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/MissingScope"
  "/tasks/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Task id.
      schema:
        type: integer
    get:
      operationId: task_lookups_show
      tags:
      - Tasks
      summary: Resolve a task reference
      description: 'Where a `/tasks/<id>` link points: the task''s board and issue key.'
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      responses:
        '200':
          description: The task's location.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/TaskLookup"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/up":
    get:
      operationId: health_show
      tags:
      - Health
      summary: Liveness probe
      description: Returns 200 when the API is up. No authentication.
      security: []
      responses:
        '200':
          description: App booted.
          content:
            text/html:
              schema:
                type: string
        '500':
          description: App failed to boot.
  "/workspace_documents/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Document id or slug (slugs are unique across workspaces).
      schema:
        type: string
    get:
      operationId: document_lookups_show
      tags:
      - Workspace documents
      summary: Resolve a document reference
      description: 'Where a `/documents/<id>` link points: the page''s workspace and slug.'
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      responses:
        '200':
          description: The document's location.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/DocumentLookup"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/workspaces":
    get:
      operationId: workspaces_index
      tags:
      - Workspaces
      summary: List the workspaces the caller can reach, with their boards
      description: Workspaces you belong to or have a board in, with the boards you can see.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      responses:
        '200':
          description: Workspaces with the caller's visible boards.
          content:
            application/json:
              schema:
                type: array
                items:
                  "$ref": "#/components/schemas/WorkspaceListItem"
              example:
              - id: 34
                name: Pixta
                slug: pixta
                description:
                boards:
                - id: 41
                  name: BoardP
                  created_at: '2025-03-02T10:11:12.000-03:00'
                  updated_at: '2026-10-01T09:00:00.000-03:00'
                  archived: false
                  visibility: visibility_workspace
                  board_columns_count: 5
                  tasks_count: 312
                  board_users_count: 2
                  board_users:
                  - id: 1
                    role: role_owner
                    email: ana@example.com
                    name: Ana
                    avatar_url:
                    is_owner: true
                  workspace:
                    id: 34
                    name: Pixta
                    slug: pixta
        '401':
          "$ref": "#/components/responses/Unauthorized"
    post:
      operationId: workspaces_create
      tags:
      - Workspaces
      summary: Create a workspace (the caller becomes its admin)
      description: Creates a workspace; you become its admin.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/WorkspaceInput"
            example:
              workspace:
                name: Pixta
                issue_prefix: PIX
      responses:
        '201':
          description: Created.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Workspace"
              example:
                id: 223
                name: Pixta
                slug: pixta
                description:
                boards: []
                workspace_users:
                - id: 1
                  role: role_admin
                  email: ana@example.com
                  name: Ana
                  avatar_url:
                workspace_documents: []
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/StatusError"
              example:
                status: 400
                error: Bad Request
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
              examples:
                blank_name:
                  value:
                    name:
                    - can't be blank
                reserved:
                  value:
                    friendly_id:
                    - is reserved
                issue_prefix:
                  value:
                    issue_prefix:
                    - has already been taken
  "/workspaces/{id}":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceIdAsId"
    get:
      operationId: workspaces_show
      tags:
      - Workspaces
      summary: Show a workspace with its boards, members and listed documents
      description: |-
        A workspace with its boards, members and documents. Users who were only added to some of its boards see just
        those boards, without members or documents.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      responses:
        '200':
          description: The workspace.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Workspace"
              example:
                id: 34
                name: Pixta
                slug: pixta
                description:
                boards:
                - id: 41
                  name: BoardP
                  created_at: '2025-03-02T10:11:12.000-03:00'
                  updated_at: '2026-10-01T09:00:00.000-03:00'
                  archived: false
                  visibility: visibility_workspace
                  board_columns_count: 5
                  tasks_count: 312
                  board_users_count: 1
                  board_users:
                  - id: 1
                    role: role_owner
                    email: ana@example.com
                    name: Ana
                    avatar_url:
                    is_owner: true
                  workspace:
                    id: 34
                    name: Pixta
                    slug: pixta
                workspace_users:
                - id: 1
                  role: role_admin
                  email: ana@example.com
                  name: Ana
                  avatar_url:
                - id: 9
                  role: role_member
                  email: bia@example.com
                  name:
                  avatar_url:
                workspace_documents:
                - id: 6
                  title: Roadmap 2026
                  slug: roadmap-2026
                  is_draft: true
                  is_workspace_public: true
                  is_public: false
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
    put:
      operationId: workspaces_update
      tags:
      - Workspaces
      summary: Rename a workspace or change its issue prefix
      description: >-
        Rename the workspace or change its issue prefix (uppercase letters and digits, starting with a letter, unique). Workspace
        admins only.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/WorkspaceInput"
            example:
              workspace:
                issue_prefix: BOARDP
      responses:
        '200':
          description: OK.
          headers:
            Location:
              schema:
                type: string
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Workspace"
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/StatusError"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
              examples:
                format:
                  value:
                    issue_prefix:
                    - is invalid
                taken:
                  value:
                    issue_prefix:
                    - has already been taken
  "/workspaces/{id}/share":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceIdAsId"
    post:
      operationId: workspaces_share
      tags:
      - Workspace members
      summary: Invite a user to the workspace by e-mail (legacy, renders the workspace)
      description: Deprecated — use `POST /workspaces/{workspace_id}/workspace_users/share`.
      deprecated: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/InviteByEmailInput"
            example:
              email: bia@example.com
      responses:
        '200':
          description: OK.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Workspace"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              examples:
                missing:
                  value:
                    error: Email is required
                invalid:
                  value:
                    error: Email is invalid
        '429':
          description: Too many requests. Retry after the time in `Retry-After`.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Too many invitations, try again later
  "/workspaces/{workspace_id}/integrations":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    get:
      operationId: workspace_integrations_index
      tags:
      - Git integrations
      summary: List the workspace's integrations
      description: The workspace's GitHub/GitLab connections and GRUPIM binding. Workspace admins only.
      responses:
        '200':
          description: Capabilities and connections.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/IntegrationsIndex"
              example:
                github_configured: true
                gitlab_configured: true
                grupim_configured: true
                connections:
                - id: 3
                  provider: github
                  host: github.com
                  installation_id: '55012345'
                  account_login:
                  account_name:
                  configured: true
                  connected_by:
                    id: 1
                    email: ana@example.com
                    name: Ana
                  repositories_count: 12
                  created_at: '2026-09-01T12:00:00.000Z'
                grupim:
                  id: 2
                  guild_id: '1291234567890123456'
                  guild_name: Pixta
                  channel_id: '1291234567890999999'
                  channel_name: lixta
                  board_id: 41
                  board_name: Product
                  notify_events:
                  - created
                  - moved
                  - commented
                  - assigned
                  - archived
                  connected_by:
                    id: 1
                    email: ana@example.com
                    name: Ana
                  members_count: 4
                  created_at: '2026-09-02T09:30:00.000Z'
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/workspaces/{workspace_id}/integrations/github/install_url":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    get:
      operationId: workspace_integrations_github_install_url
      tags:
      - Git integrations
      summary: Start the GitHub App installation
      description: >-
        URL to install the Lixta GitHub App for this workspace. Installations are verified against your GitHub account. Workspace
        admins only.
      responses:
        '200':
          description: Installation URL.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/UrlResponse"
              example:
                url: https://github.com/apps/lixta/installations/new?state=eyJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOjEyfQ.sig
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          "$ref": "#/components/responses/NotFound"
        '503':
          description: This integration is not configured.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: GitHub App is not configured on this server
  "/workspaces/{workspace_id}/integrations/gitlab/authorize_url":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    get:
      operationId: workspace_integrations_gitlab_authorize_url
      tags:
      - Git integrations
      summary: Start the GitLab OAuth authorization
      description: URL to authorize Lixta on GitLab for this workspace. Workspace admins only.
      responses:
        '200':
          description: Authorize URL.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/UrlResponse"
              example:
                url: >-
                  https://gitlab.com/oauth/authorize?client_id=abc123&redirect_uri=https%3A%2F%2Fapi.ontrama.com%2Fintegrations%2Fgitlab%2Fcallback&response_type=code&scope=api&state=eyJhbGciOiJIUzI1NiJ9.e30.sig
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          "$ref": "#/components/responses/NotFound"
        '503':
          description: This integration is not configured.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: GitLab App is not configured on this server
  "/workspaces/{workspace_id}/integrations/grupim":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    post:
      operationId: workspace_grupim_integrations_create
      tags:
      - GRUPIM integration
      summary: Bind a GRUPIM guild to the workspace (claim code)
      description: |-
        Binds the Discord server of a claim code to this workspace and board, with an optional notification channel and
        events. Workspace admins only.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/GrupimConnectionCreateRequest"
            example:
              code: ABCD-EFGH-JKLM
              channel_id: '1291234567890999999'
              board_id: 41
      responses:
        '201':
          description: Connection created.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/GrupimConnectionEnvelope"
              example:
                connection:
                  id: 2
                  guild_id: '1291234567890123456'
                  guild_name: Pixta
                  channel_id: '1291234567890999999'
                  channel_name: lixta
                  board_id: 41
                  board_name: Product
                  notify_events:
                  - created
                  - moved
                  - commented
                  - assigned
                  - archived
                  connected_by:
                    id: 1
                    email: ana@example.com
                    name: Ana
                  members_count: 0
                  created_at: '2026-09-02T09:30:00.000Z'
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Invalid or expired code. Run /trama connect in your GRUPIM server to get a new one.
        '502':
          description: GRUPIM API error (listing the channels or creating the webhook).
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Missing Permissions
        '503':
          description: This integration is not configured.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: GRUPIM integration is not configured on this server
    patch:
      operationId: workspace_grupim_integrations_update
      tags:
      - GRUPIM integration
      summary: Change the bound board, channel or notified events
      description: Changes the bound board, channel or notified events (an empty list turns notifications off). Workspace
        admins only.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/GrupimConnectionUpdateRequest"
            example:
              notify_events:
              - created
              - moved
              - commented
      responses:
        '200':
          description: Updated connection.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/GrupimConnectionEnvelope"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/StatusNotFound"
              example:
                error: GRUPIM not connected
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Channel not found
        '502':
          description: GRUPIM API error (listing channels or creating the new webhook).
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
        '503':
          description: This integration is not configured.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: GRUPIM integration is not configured on this server
    delete:
      operationId: workspace_grupim_integrations_destroy
      tags:
      - GRUPIM integration
      summary: Unbind the GRUPIM guild
      description: Unbinds the Discord server. Workspace admins only.
      responses:
        '204':
          "$ref": "#/components/responses/NoContent"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/StatusNotFound"
              example:
                error: GRUPIM not connected
        '503':
          description: This integration is not configured.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: GRUPIM integration is not configured on this server
  "/workspaces/{workspace_id}/integrations/grupim/claim":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    get:
      operationId: workspace_grupim_integrations_claim
      tags:
      - GRUPIM integration
      summary: Preview a guild claim code
      description: |-
        Checks a claim code produced by `/trama connect` (run by a server admin in Discord) and returns the server and
        its channels, without binding anything. Workspace admins only.
      parameters:
      - name: code
        in: query
        required: true
        schema:
          type: string
        example: ABCD-EFGH-JKLM
      responses:
        '200':
          description: The guild of the code and its channels.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/GrupimClaimPreview"
              example:
                claim:
                  guild_id: '1291234567890123456'
                  guild_name: Pixta
                  channel_id: '1291234567890999999'
                  requested_by: ana
                  expires_at: '2026-10-04T12:10:00.000Z'
                channels:
                - id: '1291234567890999999'
                  name: lixta
                  type: 0
                  parent_id: '1291234567890888888'
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Invalid or expired code
        '502':
          description: GRUPIM API error while listing the channels (e.g. the bot left the guild).
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Missing Access
        '503':
          description: This integration is not configured.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: GRUPIM integration is not configured on this server
  "/workspaces/{workspace_id}/integrations/grupim/invite_url":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    get:
      operationId: workspace_grupim_integrations_invite_url
      tags:
      - GRUPIM integration
      summary: Get the bot invite URL
      description: URL to add the GRUPIM bot to a Discord server. Workspace admins only.
      responses:
        '200':
          description: Invite URL.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/UrlResponse"
              example:
                url: https://grup.im/oauth2/authorize?client_id=1290000000000000000&scope=bot&permissions=536955904
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          "$ref": "#/components/responses/NotFound"
        '503':
          description: This integration is not configured.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: GRUPIM integration is not configured on this server
  "/workspaces/{workspace_id}/integrations/grupim/link":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    get:
      operationId: workspace_grupim_integrations_preview_link
      tags:
      - GRUPIM integration
      summary: Preview a GRUPIM account link code
      description: Shows which Discord account and server a `/trama link` code belongs to, without linking. Workspace members.
      parameters:
      - name: code
        in: query
        required: true
        schema:
          type: string
        example: aZ3kP9qL0mXw
      responses:
        '200':
          description: The GRUPIM account and guild of the code.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/GrupimLinkPreview"
              example:
                link_code:
                  grupim_user_id: '1290000000000000123'
                  grupim_username: ana
                  guild_id: '1291234567890123456'
                  guild_name: Pixta
                  expires_at: '2026-10-04T12:10:00.000Z'
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Not a workspace member
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Invalid or expired code
    post:
      operationId: workspace_grupim_integrations_complete_link
      tags:
      - GRUPIM integration
      summary: Link my Lixta account to a GRUPIM account (link code)
      description: Links your Lixta account to the Discord account of a `/trama link` code, after you confirmed it. Workspace
        members.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/GrupimLinkRequest"
            example:
              code: aZ3kP9qL0mXw
      responses:
        '200':
          description: Link created or re-pointed to the caller.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/GrupimLinkResponse"
              example:
                link:
                  id: 12
                  grupim_user_id: '1290000000000000123'
                  grupim_username: ana
                  user_id: 1
                  source: slash
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Not a workspace member
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Invalid or expired code
  "/workspaces/{workspace_id}/integrations/grupim/members":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    get:
      operationId: workspace_grupim_integrations_members
      tags:
      - GRUPIM integration
      summary: List guild members and their Lixta links
      description: Discord server members and the Lixta users they are linked to. Workspace admins only.
      responses:
        '200':
          description: Guild members and workspace members.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/GrupimMembersResponse"
              example:
                members:
                - grupim_user_id: '1290000000000000123'
                  username: ana
                  display_name: Ana
                  linked: true
                  lixta_user:
                    id: 1
                    email: ana@example.com
                    name: Ana
                    username: ana
                    source: slash
                - grupim_user_id: '1290000000000000456'
                  username: bruno
                  display_name: Bruno
                  linked: false
                  lixta_user:
                workspace_members:
                - id: 1
                  email: ana@example.com
                  name: Ana
                  username: ana
                  role: role_admin
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/StatusNotFound"
              example:
                error: GRUPIM not connected
        '502':
          description: GRUPIM API error (e.g. the bot lacks the members intent or left the guild).
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
        '503':
          description: This integration is not configured.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: GRUPIM integration is not configured on this server
    put:
      operationId: workspace_grupim_integrations_update_members
      tags:
      - GRUPIM integration
      summary: Map guild members to Lixta users
      description: Links Discord members to Lixta users (explicitly or by matching usernames). Workspace admins only.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/GrupimMembersUpdateRequest"
            examples:
              mapOne:
                value:
                  links:
                  - grupim_user_id: '1290000000000000456'
                    user_id: 7
                    grupim_username: bruno
                summary: Admin picks a Lixta user for a member (web app)
              unlink:
                value:
                  links:
                  - grupim_user_id: '1290000000000000456'
                    user_id:
                summary: Remove a mapping
              matchUsernames:
                value:
                  match_usernames: true
                summary: Match usernames button
      responses:
        '200':
          description: Connection after the changes.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/GrupimConnectionEnvelope"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          description: Not found, or not visible to you.
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/StatusNotFound"
              example:
                error: GRUPIM not connected
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: User is already linked to another GRUPIM account
        '502':
          description: The upstream service (GitHub, GitLab or GRUPIM) failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Missing Access
        '503':
          description: This integration is not configured.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: GRUPIM integration is not configured on this server
  "/workspaces/{workspace_id}/integrations/{id}":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    - name: id
      in: path
      required: true
      schema:
        type: integer
      example: 3
    delete:
      operationId: workspace_integrations_destroy
      tags:
      - Git integrations
      summary: Disconnect a GitHub or GitLab connection
      description: Disconnects a GitHub or GitLab connection. Workspace admins only.
      responses:
        '204':
          "$ref": "#/components/responses/NoContent"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/workspaces/{workspace_id}/integrations/{id}/repositories":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    - name: id
      in: path
      required: true
      schema:
        type: integer
      example: 3
    get:
      operationId: workspace_integrations_repositories
      tags:
      - Git integrations
      summary: Sync and list the connection's repositories
      description: Syncs and lists the connection's repositories with their enabled flag. Workspace admins only.
      responses:
        '200':
          description: All stored repositories of the connection.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/GitRepositoryList"
              example:
                repositories:
                - id: 10
                  external_id: '812345678'
                  full_name: locomotiva/tarefas-backend
                  html_url: https://github.com/locomotiva/tarefas-backend
                  enabled: true
                  webhook_id:
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          "$ref": "#/components/responses/NotFound"
        '502':
          description: The upstream service (GitHub, GitLab or GRUPIM) failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Failed to list projects
    put:
      operationId: workspace_integrations_update_repositories
      tags:
      - Git integrations
      summary: Enable or disable repositories
      description: >-
        Enables or disables repositories (`repositories[]` with boolean `enabled`). Disabled repositories are ignored by webhooks.
        Workspace admins only.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/GitRepositoriesUpdateRequest"
            example:
              repositories:
              - external_id: '48211234'
                enabled: true
      responses:
        '200':
          description: All stored repositories of the connection after the update.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/GitRepositoryList"
              example:
                repositories:
                - id: 21
                  external_id: '48211234'
                  full_name: locomotiva/tarefas
                  html_url: https://gitlab.com/locomotiva/tarefas
                  enabled: true
                  webhook_id: '9912345'
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: 'repositories must be an array of { external_id, enabled: true | false }'
        '502':
          description: The upstream service (GitHub, GitLab or GRUPIM) failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Failed to create project hook
  "/workspaces/{workspace_id}/mentionables":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    - name: q
      in: query
      required: false
      description: Matches names/e-mails, task keys and titles, and document titles (case- and accent-insensitive).
      schema:
        type: string
    get:
      operationId: mentionables_index
      tags:
      - Workspace documents
      summary: People, tasks and documents for the "@" picker
      description: People, tasks and documents of a workspace matching `q`, for "@" pickers (up to 8 each).
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      responses:
        '200':
          description: Matches by kind.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Mentionables"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/workspaces/{workspace_id}/workspace_activities":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    get:
      operationId: workspace_activities_index
      tags:
      - Workspace activity
      summary: Latest 50 task activities across the boards of the workspace the caller can see
      description: >-
        The latest 50 task activities across the boards of the workspace that you can see. Filter with `activity_types` and
        `days`.
      parameters:
      - name: activity_types
        in: query
        required: false
        style: form
        explode: true
        schema:
          type: array
          items:
            type: string
            enum:
            - activity_type_comment
            - activity_type_attachment
            - activity_type_task_created
            - activity_type_task_moved
            - activity_type_task_archived
            - activity_type_checklist_item_completed
            - activity_type_task_assigned
            - activity_type_task_due_date_changed
            - activity_type_task_updated
            - activity_type_parent_changed
            - activity_type_relation_changed
            - activity_type_pull_request_changed
        example:
        - activity_type_comment
        - activity_type_task_moved
      - name: days
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
        example: 7
      responses:
        '200':
          description: Up to 50 activities, newest first.
          content:
            application/json:
              schema:
                type: array
                maxItems: 50
                items:
                  "$ref": "#/components/schemas/WorkspaceActivity"
              example:
              - id: 4560
                activity_type: activity_type_task_moved
                body: Fix login
                data:
                  task_id: 7104
                  task_name: Fix login
                  from_column_id: 882
                  from_column_name: Todo
                  to_column_id: 883
                  to_column_name: Done
                created_at: '2026-10-04T00:17:16.842-03:00'
                updated_at: '2026-10-04T00:17:16.842-03:00'
                description: moved task to Done
                relative_time: about 2 hours
                user:
                  id: 1
                  name: Ana
                  email: ana@example.com
                  avatar_url:
                  display_name: Ana
                task:
                  id: 7104
                  name: Fix login
                  board_name: BoardP
                  board_id: 41
                board:
                  id: 41
                  name: BoardP
                from_column: Todo
                to_column: Done
              - id: 4559
                activity_type: activity_type_comment
                body: Deployed to staging
                data: {}
                created_at: '2026-10-04T00:15:00.000-03:00'
                updated_at: '2026-10-04T00:15:00.000-03:00'
                description: commented on
                relative_time: about 2 hours
                user:
                  id: 9
                  name:
                  email: bia@example.com
                  avatar_url:
                  display_name: bia@example.com
                task:
                  id: 7104
                  name: Fix login
                  board_name: BoardP
                  board_id: 41
                board:
                  id: 41
                  name: BoardP
                comment_body: Deployed to staging
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/workspaces/{workspace_id}/workspace_documents":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    get:
      operationId: workspace_documents_index
      tags:
      - Workspace documents
      summary: List the document tree (or search it)
      description: |-
        The workspace's active pages as summaries (rebuild the tree from `parent_id` and `sort_key`). `q` searches titles and
        bodies and adds an `excerpt`; `archived=true` includes archived pages. Workspace members; private pages only for their
        creator.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      parameters:
      - name: q
        in: query
        required: false
        schema:
          type: string
        example: migração
      - name: archived
        in: query
        required: false
        schema:
          type: boolean
      responses:
        '200':
          description: Document summaries.
          content:
            application/json:
              schema:
                type: array
                items:
                  "$ref": "#/components/schemas/DocumentSummary"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/MissingScope"
        '404':
          "$ref": "#/components/responses/NotFound"
    post:
      operationId: workspace_documents_create
      tags:
      - Workspace documents
      summary: Create a page
      description: |-
        Creates a page (title defaults to "Untitled"), optionally inside `parent_id` and after the sibling `after_id`.
        Members and admins.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: false
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DocumentCreateRequest"
      responses:
        '201':
          description: Created.
          headers:
            Location:
              schema:
                type: string
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Document"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/PlacementError"
  "/workspaces/{workspace_id}/workspace_documents/{id}":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    - "$ref": "#/components/parameters/DocumentId"
    get:
      operationId: workspace_documents_show
      tags:
      - Workspace documents
      summary: Show a document
      description: |-
        A page by id or slug, with its Markdown body, `lock_version`, breadcrumbs, sub-pages, backlinks (tasks and documents
        that link to it) and your permissions. Workspace members.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      responses:
        '200':
          description: The document.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Document"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/MissingScope"
        '404':
          "$ref": "#/components/responses/NotFound"
    put:
      operationId: workspace_documents_update
      tags:
      - Workspace documents
      summary: Update a document (title, body, icon, move, visibility)
      description: |-
        Updates a page: title, body, icon, parent, position, visibility. Saving `title` or `body` needs the `lock_version` you
        last read; a stale one answers 409 with the current page so nothing is overwritten silently. Members and admins.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DocumentUpdateRequest"
      responses:
        '200':
          description: Updated (or unchanged) document.
          headers:
            Location:
              schema:
                type: string
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Document"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
        '404':
          "$ref": "#/components/responses/NotFound"
        '409':
          description: See the response body.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/DocumentConflict"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/PlacementError"
              examples:
                cycle:
                  value:
                    parent_id:
                    - would create a cycle
                archivedParent:
                  value:
                    parent_id:
                    - is archived
    delete:
      operationId: workspace_documents_destroy
      tags:
      - Workspace documents
      summary: Delete an archived document (and its sub-pages)
      description: Deletes an archived page for good. Its creator or a workspace admin.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      responses:
        '204':
          "$ref": "#/components/responses/NoContent"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: The page is not archived.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Archive the document before deleting it
  "/workspaces/{workspace_id}/workspace_documents/{id}/archive":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    - "$ref": "#/components/parameters/DocumentId"
    post:
      operationId: workspace_documents_archive
      tags:
      - Workspace documents
      summary: Archive a document and its sub-pages
      description: Archives a page and its sub-pages (restorable). Members and admins.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      responses:
        '200':
          description: The document after the change.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Document"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/workspaces/{workspace_id}/workspace_documents/{id}/publish":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    - "$ref": "#/components/parameters/DocumentId"
    put:
      operationId: workspace_documents_publish
      tags:
      - Workspace documents
      summary: Publish a document (is_public = true, is_draft = false)
      description: Publishes a read-only copy anyone with the link can open. Members and admins.
      responses:
        '200':
          description: Updated document.
          headers:
            Location:
              schema:
                type: string
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Document"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Model validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
  "/workspaces/{workspace_id}/workspace_documents/{id}/restore":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    - "$ref": "#/components/parameters/DocumentId"
    post:
      operationId: workspace_documents_restore
      tags:
      - Workspace documents
      summary: Restore an archived document and its sub-pages
      description: Restores an archived page and its sub-pages. Members and admins.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      responses:
        '200':
          description: The document after the change.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Document"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/workspaces/{workspace_id}/workspace_documents/{id}/unpublish":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    - "$ref": "#/components/parameters/DocumentId"
    put:
      operationId: workspace_documents_unpublish
      tags:
      - Workspace documents
      summary: Unpublish a document (is_public = false, is_draft = true)
      description: Takes the public link down. Members and admins.
      responses:
        '200':
          description: Updated document.
          headers:
            Location:
              schema:
                type: string
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Document"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Model validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ValidationErrors"
  "/workspaces/{workspace_id}/workspace_documents/{id}/upload_presign":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    - "$ref": "#/components/parameters/DocumentId"
    post:
      operationId: workspace_documents_upload_presign
      tags:
      - Workspace documents
      summary: Presign an upload for a document (images and files pasted into the body)
      description: An upload form for an image or file in a page (S3 presigned POST). Members and admins.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PresignRequest"
            example:
              file_name: diagram.png
      responses:
        '200':
          description: Upload policy.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/PresignedUpload"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
        '429':
          description: More than 60 presigns by this user in the last hour.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
  "/workspaces/{workspace_id}/workspace_documents/{workspace_document_id}/comments":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    - "$ref": "#/components/parameters/WorkspaceDocumentId"
    get:
      operationId: document_comments_index
      tags:
      - Document comments
      summary: List a document's comment threads
      description: Comment threads on a page, oldest first, each with its replies. Workspace members.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - boards.read
      responses:
        '200':
          description: Threads with replies.
          content:
            application/json:
              schema:
                type: array
                items:
                  "$ref": "#/components/schemas/DocumentThread"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
    post:
      operationId: document_comments_create
      tags:
      - Document comments
      summary: Start a thread or reply
      description: |-
        Starts a thread (optionally quoting `anchor_text`) or replies to one (`parent_id`). Markdown; @mentions notify.
        Workspace members, viewers included.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - comments.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DocumentCommentCreateRequest"
      responses:
        '201':
          description: The comment.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/DocumentComment"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Invalid body (e.g. blank), or a reply to a comment of another document.
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: array
                  items:
                    type: string
  "/workspaces/{workspace_id}/workspace_documents/{workspace_document_id}/comments/{id}":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    - "$ref": "#/components/parameters/WorkspaceDocumentId"
    - name: id
      in: path
      required: true
      description: Comment id.
      schema:
        type: integer
    put:
      operationId: document_comments_update
      tags:
      - Document comments
      summary: Edit a comment
      description: Edits your comment.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - comments.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DocumentCommentUpdateRequest"
      responses:
        '200':
          description: The comment.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/DocumentComment"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Invalid body (e.g. blank), or a reply to a comment of another document.
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: array
                  items:
                    type: string
    patch:
      operationId: document_comments_patch
      tags:
      - Document comments
      summary: Edit a comment (PATCH)
      description: Edits your comment.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - comments.write
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DocumentCommentUpdateRequest"
      responses:
        '200':
          description: The comment.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/DocumentComment"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
        '404':
          "$ref": "#/components/responses/NotFound"
    delete:
      operationId: document_comments_destroy
      tags:
      - Document comments
      summary: Delete a comment
      description: Deletes a comment (a thread with its first comment). The author or a workspace admin.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - comments.write
      responses:
        '204':
          description: Deleted.
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/workspaces/{workspace_id}/workspace_documents/{workspace_document_id}/comments/{id}/resolve":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    - "$ref": "#/components/parameters/WorkspaceDocumentId"
    - name: id
      in: path
      required: true
      description: The thread's first comment.
      schema:
        type: integer
    put:
      operationId: document_comments_resolve
      tags:
      - Document comments
      summary: Resolve a thread
      description: Resolves a thread.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - comments.write
      responses:
        '200':
          description: The thread's first comment.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/DocumentComment"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
  "/workspaces/{workspace_id}/workspace_documents/{workspace_document_id}/comments/{id}/unresolve":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    - "$ref": "#/components/parameters/WorkspaceDocumentId"
    - name: id
      in: path
      required: true
      description: The thread's first comment.
      schema:
        type: integer
    put:
      operationId: document_comments_unresolve
      tags:
      - Document comments
      summary: Reopen a thread
      description: Reopens a resolved thread.
      security:
      - bearerAuth: []
      - apiKeyAuth: []
        apiSecretAuth: []
      - oauth2:
        - comments.write
      responses:
        '200':
          description: The thread's first comment.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/DocumentComment"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          description: 'Not allowed: your role, or an OAuth token without the required scope.'
          content:
            application/json:
              schema:
                anyOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/OAuthError"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
  "/workspaces/{workspace_id}/workspace_users":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    get:
      operationId: workspace_users_index
      tags:
      - Workspace members
      summary: List the members of a workspace
      description: Members of the workspace and their roles. Members only.
      responses:
        '200':
          description: Member rows.
          content:
            application/json:
              schema:
                type: array
                items:
                  "$ref": "#/components/schemas/WorkspaceUser"
              example:
              - id: 257
                role: role_admin
                user:
                  id: 1
                  email: ana@example.com
                  name: Ana
                  avatar_url:
              - id: 259
                role: role_viewer
                user:
                  id: 9
                  email: bia@example.com
                  name:
                  avatar_url:
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '404':
          "$ref": "#/components/responses/NotFound"
  "/workspaces/{workspace_id}/workspace_users/share":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    post:
      operationId: workspace_users_share
      tags:
      - Workspace members
      summary: Invite a user to the workspace by e-mail
      description: |-
        Invites someone by e-mail (an account is created if needed). Existing members are left as they are and not
        e-mailed again. Workspace admins only. Invalid e-mail → 422; throttled (429).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/InviteByEmailInput"
            example:
              email: bia@example.com
      responses:
        '200':
          description: Invitation processed (new member), or the user was already a member (no change, no e-mail).
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/MessageResponse"
              examples:
                invited:
                  value:
                    message: User invited successfully
                already_member:
                  value:
                    message: User is already a member
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              examples:
                blank:
                  value:
                    error: Email is required
                invalid:
                  value:
                    error: Email is invalid
                failed:
                  value:
                    error: Failed to invite user
        '429':
          description: Too many requests. Retry after the time in `Retry-After`.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              example:
                error: Too many invitations, try again later
  "/workspaces/{workspace_id}/workspace_users/{id}":
    parameters:
    - "$ref": "#/components/parameters/WorkspaceId"
    - name: id
      in: path
      required: true
      schema:
        type: integer
      example: 259
    put:
      operationId: workspace_users_update
      tags:
      - Workspace members
      summary: Change a member's role
      description: >-
        Changes a member's role (`role_viewer`, `role_member`, `role_admin`). A workspace always keeps at least one admin.
        Workspace admins only.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/WorkspaceUserRoleInput"
            example:
              workspace_user:
                role: role_viewer
      responses:
        '200':
          description: Role saved.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/MessageResponse"
              example:
                message: User role updated successfully
        '400':
          description: Missing or malformed parameters.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/StatusError"
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                oneOf:
                - "$ref": "#/components/schemas/ErrorMessage"
                - "$ref": "#/components/schemas/ValidationErrors"
              examples:
                last_admin:
                  value:
                    error: Cannot change role - you are the only admin
                invalid_role:
                  value:
                    role:
                    - is not included in the list
    delete:
      operationId: workspace_users_destroy
      tags:
      - Workspace members
      summary: Remove a member from the workspace
      description: |-
        Removes a member from the workspace and from its boards; boards they owned move to the admin removing them. A
        workspace always keeps at least one admin. Workspace admins only.
      responses:
        '200':
          description: Removed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/MessageResponse"
              example:
                message: User removed from workspace successfully
        '401':
          "$ref": "#/components/responses/Unauthorized"
        '403':
          "$ref": "#/components/responses/ForbiddenWorkspaceManage"
        '404':
          "$ref": "#/components/responses/NotFound"
        '422':
          description: Validation failed.
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorMessage"
              examples:
                own_row:
                  value:
                    error: Cannot remove yourself - you are the only admin
                other_row:
                  value:
                    error: Cannot remove the only admin
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'JWT from `POST /login`. Send `Authorization: Bearer <jwt>`.'
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-Api-Key
      description: Personal API key. Always sent together with `X-Api-Secret`.
    apiSecretAuth:
      type: apiKey
      in: header
      name: X-Api-Secret
      description: Personal API secret (shown once, by `POST /me/api_credentials/regenerate`).
    oauth2:
      type: oauth2
      description: OAuth 2.1 authorization code + PKCE (S256), public clients. Access tokens look like `lxt_at_…`.
      flows:
        authorizationCode:
          authorizationUrl: https://ontrama.com/oauth2/authorize
          tokenUrl: https://api.ontrama.com/oauth2/token
          refreshUrl: https://api.ontrama.com/oauth2/token
          scopes:
            boards.read: Read boards and tasks
            boards.write: Create and update tasks
            comments.write: Add comments
  parameters:
    WorkspaceIdAsId:
      name: id
      in: path
      required: true
      schema:
        oneOf:
        - type: integer
        - type: string
      example: pixta
      description: Workspace id or slug.
    WorkspaceId:
      name: workspace_id
      in: path
      required: true
      schema:
        oneOf:
        - type: integer
        - type: string
      example: pixta
      description: Workspace id or slug.
    DocumentId:
      name: id
      in: path
      required: true
      schema:
        oneOf:
        - type: string
        - type: integer
      example: release-plan
    WorkspaceDocumentId:
      name: workspace_document_id
      in: path
      required: true
      schema:
        oneOf:
        - type: string
        - type: integer
      example: 45
    BoardId:
      name: board_id
      in: path
      required: true
      schema:
        type: integer
      example: 41
      description: Board id.
    BoardIdAsId:
      name: id
      in: path
      required: true
      schema:
        type: integer
      example: 41
      description: Board id.
    TaskIdOrIssueKey:
      name: id
      in: path
      required: true
      schema:
        oneOf:
        - type: integer
        - type: string
          pattern: "^[A-Za-z][A-Za-z0-9]*-\\d+$"
      example: BOARDP-1377
      description: Task id or issue key (`PREFIX-123`).
    TaskId:
      name: task_id
      in: path
      required: true
      description: Task id (numeric).
      schema:
        type: integer
      example: 7104
    Id:
      name: id
      in: path
      required: true
      description: Id of the resource.
      schema:
        type: integer
  responses:
    Unauthorized:
      description: Missing or invalid credentials.
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/ErrorMessage"
          example:
            error: User authentication failed
    NoContent:
      description: No content.
    NotFound:
      description: Not found, or not visible to you.
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/StatusNotFound"
          example:
            status: 404
            error: Not Found
    MissingScope:
      description: OAuth token without the required scope, or an operation OAuth tokens cannot use.
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/OAuthError"
          examples:
            missingScope:
              value:
                error: missing_scope
                error_description: 'Required scope: boards.write'
            notAllowlisted:
              value:
                error: missing_scope
                error_description: This endpoint is not available to OAuth tokens
    ForbiddenWorkspaceManage:
      description: Workspace admins only.
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/ErrorMessage"
          example:
            error: Not authorized to manage this workspace
    ForbiddenBoardEdit:
      description: You need edit rights on this board (member, admin or owner, or workspace admin).
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/ErrorMessage"
          example:
            error: Not authorized to edit this board
    ForbiddenBoardManage:
      description: You need manage rights on this board (admin or owner, or workspace admin).
      content:
        application/json:
          schema:
            "$ref": "#/components/schemas/ErrorMessage"
          example:
            error: Not authorized to manage this board
  schemas:
    PresignRequest:
      type: object
      required:
      - file_name
      properties:
        file_name:
          type: string
          example: Me at the beach.PNG
    PresignedUpload:
      type: object
      required:
      - url
      - fields
      - public_url
      - content_type
      - max_bytes
      properties:
        url:
          type: string
          format: uri
          example: https://s3.sa-east-1.amazonaws.com/lixtame-public
        fields:
          type: object
          additionalProperties:
            type: string
          example:
            key: uploads/me-at-the-beach_3f9a1c2b.png
            Content-Type: image/png
            policy: eyJleHBpcmF0aW9uIjoiMjAyNi0xMC0wNFQwNDozNDoxNFoiLCJjb25kaXRpb25zIjpbXX0=
            x-amz-credential: AKIA…/20261004/sa-east-1/s3/aws4_request
            x-amz-algorithm: AWS4-HMAC-SHA256
            x-amz-date: 20261004T041914Z
            x-amz-signature: bdc2675e8f4e495e3d57f4a3b0b694a8e89d61ab585d1f7ba3a1b00e0a6d5bba
        public_url:
          type: string
          format: uri
          example: https://s3.sa-east-1.amazonaws.com/lixtame-public/uploads/me-at-the-beach_3f9a1c2b.png
        content_type:
          type: string
          example: image/png
        max_bytes:
          type: integer
          example: 5242880
    ErrorMessage:
      type: object
      required:
      - error
      properties:
        error:
          type: string
    LoginRequest:
      type: object
      required:
      - email
      properties:
        email:
          type: string
          example: you@example.com
        otp:
          type: string
          example: '482193'
    email:
      type: string
    User:
      type: object
      required:
      - id
      - email
      - created_at
      - updated_at
      properties:
        id:
          type: integer
          example: 12
        email:
          "$ref": "#/components/schemas/email"
        name:
          type: string
          nullable: true
          example: João Netto
        avatar_url:
          type: string
          nullable: true
          example: https://s3.sa-east-1.amazonaws.com/lixtame-public/uploads/me_3f9a1c2b.png
        cellphone:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    LoginResponse:
      type: object
      required:
      - user
      - token
      properties:
        user:
          "$ref": "#/components/schemas/User"
        token:
          type: string
          example: eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEyLCJleHAiOjE3NTk2MjI0MDB9.Zx1…
    LoginOtpSent:
      type: object
      properties:
        job_id:
          type: string
          format: uuid
    UserUpdateRequest:
      type: object
      required:
      - user
      properties:
        user:
          type: object
          properties:
            name:
              type: string
              nullable: true
            cellphone:
              type: string
              nullable: true
            avatar_url:
              type: string
              nullable: true
            username:
              type: string
              nullable: true
      example:
        user:
          name: João Netto
          avatar_url: https://s3.sa-east-1.amazonaws.com/lixtame-public/uploads/me_3f9a1c2b.png
    ValidationErrors:
      type: object
      additionalProperties:
        type: array
        items:
          type: string
    api_key:
      type: string
      nullable: true
    api_secret:
      type: string
      nullable: true
    ApiCredentials:
      type: object
      required:
      - api_key
      - api_secret
      - token
      - mcp_url
      properties:
        api_key:
          "$ref": "#/components/schemas/api_key"
        api_secret:
          "$ref": "#/components/schemas/api_secret"
        token:
          type: string
          nullable: true
          example: 9f2c4e1a7b3d5f60a1b2c3d4e5f60718.0a1b2c3d4e5f60718293a4b5c6d7e8f9
        mcp_url:
          type: string
          format: uri
          example: https://mcp.ontrama.com/mcp
        reset_at:
          type: string
          format: date-time
          nullable: true
    scopes:
      type: array
      items:
        type: string
        enum:
        - boards.read
        - boards.write
        - comments.write
    resource:
      type: string
      nullable: true
    expires_at:
      type: string
      format: date-time
    ConnectedApp:
      type: object
      required:
      - id
      - client_id
      - client_name
      - scopes
      - created_at
      - expires_at
      properties:
        id:
          type: integer
          example: 3
        client_id:
          type: string
          format: uuid
        client_name:
          type: string
          example: Claude
        scopes:
          "$ref": "#/components/schemas/scopes"
        resource:
          "$ref": "#/components/schemas/resource"
        created_at:
          type: string
          format: date-time
        last_used_at:
          type: string
          format: date-time
          nullable: true
        expires_at:
          "$ref": "#/components/schemas/expires_at"
    OAuthError:
      type: object
      required:
      - error
      properties:
        error:
          type: string
          example: invalid_grant
        error_description:
          type: string
    priority:
      type: string
      enum:
      - priority_none
      - priority_low
      - priority_medium
      - priority_high
      - priority_urgent
      default: priority_none
    sort_key:
      type: string
      nullable: true
    issue_number:
      type: integer
      nullable: true
    Tag:
      type: object
      properties:
        id:
          type: integer
        board_id:
          type: integer
        user_id:
          type: integer
        name:
          type: string
          nullable: true
        color:
          type: string
          nullable: true
        lower_tag:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      example:
        id: 21
        board_id: 41
        user_id: 1
        name: backend
        color: "#d1d5db"
        lower_tag:
        created_at: '2026-03-27T23:42:40.746-03:00'
        updated_at: '2026-03-27T23:42:40.746-03:00'
    parent_id:
      type: integer
      nullable: true
    SubIssuesProgress:
      type: object
      properties:
        completed:
          type: integer
        total:
          type: integer
    blocked:
      type: boolean
    is_done:
      type: boolean
    provider:
      type: string
      enum:
      - github
      - gitlab
    status:
      type: string
      enum:
      - draft
      - open
      - closed
      - merged
      default: open
    review_state:
      type: string
      enum:
      - pending
      - approved
      - changes_requested
      default: pending
    ci_status:
      type: string
      enum:
      - none
      - pending
      - success
      - failure
      default: none
    PullRequestSummary:
      type: object
      properties:
        id:
          type: integer
        provider:
          "$ref": "#/components/schemas/provider"
        number:
          type: integer
        url:
          type: string
        title:
          type: string
          nullable: true
        status:
          "$ref": "#/components/schemas/status"
        review_state:
          "$ref": "#/components/schemas/review_state"
        ci_status:
          "$ref": "#/components/schemas/ci_status"
        display_ref:
          type: string
          example: "!7"
    CardRelations:
      type: object
      required:
      - parent_id
      - parent_issue_key
      - sub_issues_progress
      - blocked
      - blocks_count
      - is_done
      - pull_requests
      properties:
        parent_id:
          "$ref": "#/components/schemas/parent_id"
        parent_issue_key:
          type: string
          nullable: true
          example: BOARDP-1200
        sub_issues_progress:
          "$ref": "#/components/schemas/SubIssuesProgress"
        blocked:
          "$ref": "#/components/schemas/blocked"
        blocks_count:
          type: integer
        is_done:
          "$ref": "#/components/schemas/is_done"
        pull_requests:
          type: array
          items:
            "$ref": "#/components/schemas/PullRequestSummary"
    AssignedTask:
      allOf:
      - type: object
        properties:
          id:
            type: integer
            example: 7104
          name:
            type: string
            nullable: true
          priority:
            "$ref": "#/components/schemas/priority"
          due_at:
            type: string
            format: date-time
            nullable: true
          board_column_id:
            type: integer
          board_id:
            type: integer
          sort_key:
            "$ref": "#/components/schemas/sort_key"
          issue_number:
            "$ref": "#/components/schemas/issue_number"
          issue_key:
            type: string
            nullable: true
            example: BOARDP-1377
          tags:
            type: array
            items:
              "$ref": "#/components/schemas/Tag"
          board:
            type: object
            properties:
              id:
                type: integer
              name:
                type: string
              workspace_id:
                type: integer
          column:
            type: object
            properties:
              id:
                type: integer
              name:
                type: string
      - "$ref": "#/components/schemas/CardRelations"
    email_enabled:
      type: boolean
      default: true
    email_types:
      type: object
      additionalProperties:
        type: boolean
      default: {}
    NotificationPreferences:
      type: object
      required:
      - id
      - email_enabled
      - email_types
      - created_at
      - updated_at
      properties:
        id:
          type: integer
        email_enabled:
          "$ref": "#/components/schemas/email_enabled"
        email_types:
          "$ref": "#/components/schemas/email_types"
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      example:
        id: 12
        email_enabled: true
        email_types:
          task_moved: false
        created_at: '2025-03-01T10:00:00.000-03:00'
        updated_at: '2026-10-04T09:00:00.000-03:00'
    NotificationPreferencesUpdateRequest:
      type: object
      required:
      - notification_preference
      properties:
        notification_preference:
          type: object
          properties:
            email_enabled:
              type: boolean
            email_types:
              type: object
              additionalProperties:
                type: boolean
      example:
        notification_preference:
          email_enabled: true
          email_types:
            added_to_workspace: true
            added_to_board: true
            added_to_task: true
            task_moved: false
            task_archived: true
    notification_type:
      type: string
      enum:
      - added_to_workspace
      - added_to_board
      - added_to_task
      - task_moved
      - task_archived
      - user_mentioned_in_comment
      - user_mentioned_in_document
      - user_mentioned_in_document_comment
      - document_comment_reply
      - document_comment
    read_at:
      type: string
      format: date-time
      nullable: true
    NotificationMetadata:
      type: object
      additionalProperties: true
    Notification:
      type: object
      required:
      - id
      - notification_type
      - created_at
      - updated_at
      - description
      - relative_time
      properties:
        id:
          type: integer
        notification_type:
          "$ref": "#/components/schemas/notification_type"
        read_at:
          "$ref": "#/components/schemas/read_at"
        metadata:
          "$ref": "#/components/schemas/NotificationMetadata"
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        description:
          type: string
          example: Task 'Fix login redirect' was moved to Done
        relative_time:
          type: string
          example: about 3 hours
      example:
        id: 5512
        notification_type: task_moved
        read_at:
        metadata:
          task_id: 7104
          task_name: Fix login redirect
          board_id: 41
          board_name: Lixta backlog
          from_column_id: 210
          from_column_name: Doing
          to_column_id: 212
          to_column_name: Done
          workspace_id: 3
          workspace_name: pixta
          moved_by_user_id: 9
          moved_by_user_name: Ana
        created_at: '2026-10-04T09:12:00.000-03:00'
        updated_at: '2026-10-04T09:12:00.000-03:00'
        description: Task 'Fix login redirect' was moved to Done
        relative_time: about 3 hours
    NotificationsMarkAllRead:
      type: object
      required:
      - message
      - updated_count
      properties:
        message:
          type: string
          enum:
          - All notifications marked as read
        updated_count:
          type: integer
      example:
        message: All notifications marked as read
        updated_count: 4
    NotificationsUnreadCount:
      type: object
      required:
      - unread_count
      properties:
        unread_count:
          type: integer
      example:
        unread_count: 4
    StatusNotFound:
      type: object
      properties:
        status:
          type: integer
          example: 404
        error:
          type: string
          example: Not Found
    UserSummary:
      type: object
      properties:
        id:
          type: integer
        email:
          type: string
          format: email
        name:
          type: string
          nullable: true
        avatar_url:
          type: string
          nullable: true
    SearchResult:
      type: object
      required:
      - id
      - searchable_id
      - searchable_type
      properties:
        id:
          type: integer
        content:
          type: string
        searchable_id:
          type: integer
        searchable_type:
          type: string
          enum:
          - Board
          - Task
          - TaskActivity
          - WorkspaceDocument
        board_id:
          type: integer
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        position:
          type: integer
        task:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
              nullable: true
            board_name:
              type: string
        board:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
            description:
              type: string
              nullable: true
            workspace_name:
              type: string
              nullable: true
        title:
          type: string
          nullable: true
        icon:
          type: string
          nullable: true
        workspace_slug:
          type: string
          nullable: true
        workspace_document:
          type: object
          properties:
            id:
              type: integer
            slug:
              type: string
            title:
              type: string
              nullable: true
            icon:
              type: string
              nullable: true
            parent_id:
              type: integer
              nullable: true
            workspace_id:
              type: integer
            workspace_slug:
              type: string
              nullable: true
            workspace_name:
              type: string
              nullable: true
        task_activity:
          type: object
          properties:
            id:
              type: integer
            activity_type:
              type: string
              enum:
              - activity_type_comment
            body:
              type: string
              nullable: true
            user:
              "$ref": "#/components/schemas/UserSummary"
            board_name:
              type: string
            task_id:
              type: integer
            task_name:
              type: string
              nullable: true
      example:
        id: 90211
        content: Fix login redirect The OTP link drops the email param
        searchable_id: 7104
        searchable_type: Task
        board_id: 41
        created_at: '2026-09-30T10:12:00.000-03:00'
        updated_at: '2026-10-02T08:40:00.000-03:00'
        position: 0
        task:
          id: 7104
          name: Fix login redirect
          board_name: Lixta backlog
    OAuthScope:
      type: string
      enum:
      - boards.read
      - boards.write
      - comments.write
    AuthorizationServerMetadata:
      type: object
      required:
      - issuer
      - authorization_endpoint
      - token_endpoint
      - revocation_endpoint
      - registration_endpoint
      - response_types_supported
      - grant_types_supported
      - code_challenge_methods_supported
      - token_endpoint_auth_methods_supported
      - scopes_supported
      - revocation_endpoint_auth_methods_supported
      properties:
        issuer:
          type: string
          format: uri
          example: https://api.ontrama.com
        authorization_endpoint:
          type: string
          format: uri
          example: https://ontrama.com/oauth2/authorize
        token_endpoint:
          type: string
          format: uri
          example: https://api.ontrama.com/oauth2/token
        revocation_endpoint:
          type: string
          format: uri
          example: https://api.ontrama.com/oauth2/revoke
        registration_endpoint:
          type: string
          format: uri
          example: https://api.ontrama.com/oauth2/register
        response_types_supported:
          type: array
          items:
            type: string
            enum:
            - code
        grant_types_supported:
          type: array
          items:
            type: string
            enum:
            - authorization_code
            - refresh_token
        code_challenge_methods_supported:
          type: array
          items:
            type: string
            enum:
            - S256
        token_endpoint_auth_methods_supported:
          type: array
          items:
            type: string
            enum:
            - none
        scopes_supported:
          type: array
          items:
            "$ref": "#/components/schemas/OAuthScope"
        revocation_endpoint_auth_methods_supported:
          type: array
          items:
            type: string
            enum:
            - none
      example:
        issuer: https://api.ontrama.com
        authorization_endpoint: https://ontrama.com/oauth2/authorize
        token_endpoint: https://api.ontrama.com/oauth2/token
        revocation_endpoint: https://api.ontrama.com/oauth2/revoke
        registration_endpoint: https://api.ontrama.com/oauth2/register
        response_types_supported:
        - code
        grant_types_supported:
        - authorization_code
        - refresh_token
        code_challenge_methods_supported:
        - S256
        token_endpoint_auth_methods_supported:
        - none
        scopes_supported:
        - boards.read
        - boards.write
        - comments.write
        revocation_endpoint_auth_methods_supported:
        - none
    OAuthScopeDetail:
      type: object
      required:
      - scope
      - label
      - description
      properties:
        scope:
          "$ref": "#/components/schemas/OAuthScope"
        label:
          type: string
          example: Read boards and tasks
        description:
          type: string
          example: View boards, columns, and task details you already can access.
    AuthorizePreview:
      type: object
      required:
      - client
      - scope
      - scopes
      - scopes_detail
      - response_type
      - redirect_uri_valid
      properties:
        client:
          type: object
          required:
          - client_id
          - name
          properties:
            client_id:
              type: string
              format: uuid
            name:
              type: string
        scope:
          type: string
          example: boards.read boards.write comments.write
        scopes:
          type: array
          items:
            "$ref": "#/components/schemas/OAuthScope"
        scopes_detail:
          type: array
          items:
            "$ref": "#/components/schemas/OAuthScopeDetail"
        response_type:
          type: string
        redirect_uri:
          type: string
          nullable: true
        state:
          type: string
          nullable: true
        redirect_uri_valid:
          type: boolean
        resource:
          type: string
          nullable: true
      example:
        client:
          client_id: 4a6f0d7e-2c55-4f0b-9a63-0a8e3c7b1f20
          name: Claude
        scope: boards.read boards.write comments.write
        scopes:
        - boards.read
        - boards.write
        - comments.write
        scopes_detail:
        - scope: boards.read
          label: Read boards and tasks
          description: View boards, columns, and task details you already can access.
        - scope: boards.write
          label: Create and update tasks
          description: Create tasks, move cards, and update metadata on boards you can edit.
        - scope: comments.write
          label: Add comments
          description: Post comments on tasks you can edit.
        response_type: code
        redirect_uri: https://claude.ai/api/mcp/auth_callback
        state: af0ifjsldkj
        redirect_uri_valid: true
        resource: https://mcp.ontrama.com/mcp
    AuthorizeRequest:
      type: object
      required:
      - client_id
      - redirect_uri
      properties:
        client_id:
          type: string
          format: uuid
        response_type:
          type: string
          enum:
          - code
          default: code
        redirect_uri:
          type: string
        scope:
          type: string
        state:
          type: string
        code_challenge:
          type: string
        code_challenge_method:
          type: string
          enum:
          - S256
          default: S256
        resource:
          type: string
      example:
        client_id: 4a6f0d7e-2c55-4f0b-9a63-0a8e3c7b1f20
        response_type: code
        redirect_uri: https://claude.ai/api/mcp/auth_callback
        scope: boards.read boards.write comments.write
        state: af0ifjsldkj
        code_challenge: E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
        code_challenge_method: S256
        resource: https://mcp.ontrama.com/mcp
    AuthorizeRedirect:
      type: object
      required:
      - type
      properties:
        type:
          type: string
          enum:
          - redirect
          - oob
        url:
          type: string
          example: https://claude.ai/api/mcp/auth_callback?code=ac_Q2x…&state=af0ifjsldkj
        code:
          type: string
        state:
          type: string
          nullable: true
    AuthorizeResponse:
      type: object
      required:
      - success
      - mode
      - code
      - scopes
      - redirect
      properties:
        success:
          type: boolean
          enum:
          - true
        mode:
          type: string
          enum:
          - code
        code:
          type: string
          example: ac_Q2xhdWRlIGlzIGEgZ29vZCBjb2RlIGZvciB0aGlzIGV4YW1wbGU
        state:
          type: string
          nullable: true
        scopes:
          type: array
          items:
            "$ref": "#/components/schemas/OAuthScope"
        redirect:
          "$ref": "#/components/schemas/AuthorizeRedirect"
      example:
        success: true
        mode: code
        code: ac_Q2xhdWRlIGlzIGEgZ29vZCBjb2RlIGZvciB0aGlzIGV4YW1wbGU
        state: af0ifjsldkj
        scopes:
        - boards.read
        - boards.write
        - comments.write
        redirect:
          type: redirect
          url: https://claude.ai/api/mcp/auth_callback?code=ac_Q2xhdWRlIGlzIGEgZ29vZCBjb2RlIGZvciB0aGlzIGV4YW1wbGU&state=af0ifjsldkj
    redirect_uris:
      type: array
      items:
        type: string
      minItems: 1
    OAuthClientRegistrationRequest:
      type: object
      required:
      - redirect_uris
      properties:
        redirect_uris:
          "$ref": "#/components/schemas/redirect_uris"
        client_name:
          type: string
          default: MCP Client
        token_endpoint_auth_method:
          type: string
          enum:
          - none
          default: none
        grant_types:
          type: array
          items:
            type: string
          default:
          - authorization_code
          - refresh_token
        response_types:
          type: array
          items:
            type: string
          default:
          - code
        scope:
          oneOf:
          - type: string
          - type: array
            items:
              type: string
          example: boards.read boards.write comments.write
      example:
        client_name: Claude
        redirect_uris:
        - https://claude.ai/api/mcp/auth_callback
        token_endpoint_auth_method: none
        grant_types:
        - authorization_code
        - refresh_token
        response_types:
        - code
        scope: boards.read boards.write comments.write
    scope:
      type: string
      example: boards.read boards.write comments.write
    OAuthClientRegistration:
      type: object
      required:
      - client_id
      - client_id_issued_at
      - client_name
      - redirect_uris
      - grant_types
      - response_types
      - token_endpoint_auth_method
      - scope
      properties:
        client_id:
          type: string
          format: uuid
        client_id_issued_at:
          type: integer
        client_name:
          type: string
        redirect_uris:
          type: array
          items:
            type: string
        grant_types:
          type: array
          items:
            type: string
            enum:
            - authorization_code
            - refresh_token
        response_types:
          type: array
          items:
            type: string
            enum:
            - code
        token_endpoint_auth_method:
          type: string
          enum:
          - none
        scope:
          "$ref": "#/components/schemas/scope"
      example:
        client_id: 4a6f0d7e-2c55-4f0b-9a63-0a8e3c7b1f20
        client_id_issued_at: 1759579200
        client_name: Claude
        redirect_uris:
        - https://claude.ai/api/mcp/auth_callback
        grant_types:
        - authorization_code
        - refresh_token
        response_types:
        - code
        token_endpoint_auth_method: none
        scope: boards.read boards.write comments.write
    RevokeRequest:
      type: object
      properties:
        token:
          type: string
        client_id:
          type: string
          format: uuid
      example:
        token: lxt_rt_9KfJ2mWq7Lx0aP3vR8sT1yU6bN4cD5eG2hI0jK7lM3n
        client_id: 4a6f0d7e-2c55-4f0b-9a63-0a8e3c7b1f20
    TokenRequest:
      type: object
      required:
      - grant_type
      - client_id
      properties:
        grant_type:
          type: string
          enum:
          - authorization_code
          - refresh_token
        client_id:
          type: string
          format: uuid
        code:
          type: string
        redirect_uri:
          type: string
        code_verifier:
          type: string
        refresh_token:
          type: string
        resource:
          type: string
      example:
        grant_type: authorization_code
        client_id: 4a6f0d7e-2c55-4f0b-9a63-0a8e3c7b1f20
        code: ac_Q2xhdWRlIGlzIGEgZ29vZCBjb2RlIGZvciB0aGlzIGV4YW1wbGU
        redirect_uri: https://claude.ai/api/mcp/auth_callback
        code_verifier: dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
        resource: https://mcp.ontrama.com/mcp
    TokenResponse:
      type: object
      required:
      - access_token
      - token_type
      - expires_in
      - refresh_token
      - scope
      properties:
        access_token:
          type: string
          example: lxt_at_Vt3x0kq1yR8w2-JmX5dQeN7cP4uL9aZbH6sGf0TiWoE
        token_type:
          type: string
          enum:
          - Bearer
        expires_in:
          type: integer
          example: 604800
        refresh_token:
          type: string
          example: lxt_rt_9KfJ2mWq7Lx0aP3vR8sT1yU6bN4cD5eG2hI0jK7lM3n
        scope:
          type: string
          example: boards.read boards.write comments.write
        resource:
          type: string
          example: https://mcp.ontrama.com/mcp
    PublicDocument:
      type: object
      required:
      - title
      - icon
      - body
      - updated_at
      - workspace_name
      properties:
        title:
          type: string
        icon:
          type: string
          nullable: true
        body:
          type: string
          nullable: true
        updated_at:
          type: string
          format: date-time
        workspace_name:
          type: string
          nullable: true
      example:
        title: Changelog
        icon: "\U0001F4E3"
        body: |-
          # v2

          - Documents
        updated_at: '2026-10-04T19:51:17.480-03:00'
        workspace_name: Acme
    DocumentLookup:
      type: object
      required:
      - id
      - workspace_slug
      - slug
      properties:
        id:
          type: integer
        workspace_id:
          type: integer
        workspace_slug:
          type: string
        slug:
          type: string
        title:
          type: string
        archived_at:
          type: string
          format: date-time
          nullable: true
      example:
        id: 45
        workspace_id: 34
        workspace_slug: acme
        slug: release-plan
        title: Release plan
        archived_at:
    slug:
      type: string
      nullable: true
      example: pixta
    visibility:
      type: string
      enum:
      - visibility_private
      - visibility_workspace
      - visibility_public
      default: visibility_private
    role:
      type: string
      enum:
      - role_viewer
      - role_member
      - role_admin
      - role_owner
      default: role_member
    WorkspaceBoardMember:
      type: object
      properties:
        id:
          type: integer
        role:
          "$ref": "#/components/schemas/role"
        email:
          type: string
          format: email
        name:
          type: string
          nullable: true
        avatar_url:
          type: string
          nullable: true
        is_owner:
          type: boolean
    WorkspaceRef:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
          nullable: true
        slug:
          type: string
          nullable: true
    WorkspaceBoard:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        archived:
          type: boolean
          nullable: true
        visibility:
          "$ref": "#/components/schemas/visibility"
        board_columns_count:
          type: integer
        tasks_count:
          type: integer
        board_users_count:
          type: integer
        board_users:
          type: array
          items:
            "$ref": "#/components/schemas/WorkspaceBoardMember"
        workspace:
          "$ref": "#/components/schemas/WorkspaceRef"
    WorkspaceListItem:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
          nullable: true
        slug:
          "$ref": "#/components/schemas/slug"
        description:
          type: string
          nullable: true
        boards:
          type: array
          items:
            "$ref": "#/components/schemas/WorkspaceBoard"
    issue_prefix:
      type: string
      nullable: true
      example: BOARDP
    WorkspaceInput:
      type: object
      properties:
        workspace:
          type: object
          properties:
            name:
              type: string
              nullable: true
            issue_prefix:
              "$ref": "#/components/schemas/issue_prefix"
    role-2:
      type: string
      nullable: true
      enum:
      - role_member
      - role_admin
      - role_viewer
      -
      default: role_member
    WorkspaceMemberFlat:
      type: object
      properties:
        id:
          type: integer
        role:
          "$ref": "#/components/schemas/role-2"
        email:
          type: string
          format: email
        name:
          type: string
          nullable: true
        avatar_url:
          type: string
          nullable: true
    slug-2:
      type: string
      example: roadmap-2026
    is_draft:
      type: boolean
      nullable: true
      default: true
    is_workspace_public:
      type: boolean
      nullable: true
      default: true
    is_public:
      type: boolean
      nullable: true
      default: false
    WorkspaceDocumentSummary:
      type: object
      properties:
        id:
          type: integer
        title:
          type: string
        slug:
          "$ref": "#/components/schemas/slug-2"
        is_draft:
          "$ref": "#/components/schemas/is_draft"
        is_workspace_public:
          "$ref": "#/components/schemas/is_workspace_public"
        is_public:
          "$ref": "#/components/schemas/is_public"
    Workspace:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
          nullable: true
        slug:
          "$ref": "#/components/schemas/slug"
        description:
          type: string
          nullable: true
        boards:
          type: array
          items:
            "$ref": "#/components/schemas/WorkspaceBoard"
        workspace_users:
          type: array
          items:
            "$ref": "#/components/schemas/WorkspaceMemberFlat"
        workspace_documents:
          type: array
          items:
            "$ref": "#/components/schemas/WorkspaceDocumentSummary"
    StatusError:
      type: object
      properties:
        status:
          type: integer
          example: 400
        error:
          type: string
          example: Bad Request
    InviteByEmailInput:
      type: object
      required:
      - email
      properties:
        email:
          type: string
          format: email
    Mentionables:
      type: object
      required:
      - people
      - tasks
      - documents
      properties:
        people:
          type: array
          items:
            type: object
            required:
            - id
            - name
            - email
            - avatar_url
            properties:
              id:
                type: integer
              name:
                type: string
                nullable: true
              email:
                type: string
              avatar_url:
                type: string
                nullable: true
        tasks:
          type: array
          items:
            type: object
            required:
            - id
            - issue_key
            - name
            - board_id
            - board_name
            - is_done
            properties:
              id:
                type: integer
              issue_key:
                type: string
                nullable: true
              name:
                type: string
              board_id:
                type: integer
              board_name:
                type: string
              is_done:
                type: boolean
        documents:
          type: array
          items:
            type: object
            required:
            - id
            - slug
            - title
            - icon
            - parent_title
            properties:
              id:
                type: integer
              slug:
                type: string
              title:
                type: string
              icon:
                type: string
                nullable: true
              parent_title:
                type: string
                nullable: true
      example:
        people:
        - id: 7
          name: Ana
          email: ana@example.com
          avatar_url:
        tasks:
        - id: 123
          issue_key: PROJ-12
          name: Fix the login
          board_id: 41
          board_name: Product
          is_done: false
        documents:
        - id: 45
          slug: release-plan
          title: Release plan
          icon: "\U0001F680"
          parent_title: Product
    activity_type:
      type: string
      enum:
      - activity_type_comment
      - activity_type_attachment
      - activity_type_task_created
      - activity_type_task_moved
      - activity_type_task_archived
      - activity_type_checklist_item_completed
      - activity_type_task_assigned
      - activity_type_task_due_date_changed
      - activity_type_task_updated
      - activity_type_parent_changed
      - activity_type_relation_changed
      - activity_type_pull_request_changed
      default: activity_type_comment
    WorkspaceActivity:
      type: object
      properties:
        id:
          type: integer
        activity_type:
          "$ref": "#/components/schemas/activity_type"
        body:
          type: string
          nullable: true
        data:
          type: object
          additionalProperties: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        description:
          type: string
          example: moved task to Done
        relative_time:
          type: string
          example: about 2 hours
        user:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
              nullable: true
            email:
              type: string
              format: email
            avatar_url:
              type: string
              nullable: true
            display_name:
              type: string
        task:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
              nullable: true
            board_name:
              type: string
              nullable: true
            board_id:
              type: integer
        board:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
              nullable: true
        comment_body:
          type: string
          nullable: true
        attachment_url:
          type: string
          nullable: true
        image_preview_url:
          type: string
        from_column:
          type: string
          nullable: true
        to_column:
          type: string
          nullable: true
        checklist_item_name:
          type: string
          nullable: true
        assigned_user_name:
          type: string
          nullable: true
        old_due_date:
          type: string
          nullable: true
        new_due_date:
          type: string
          nullable: true
    parent_id-2:
      type: integer
      nullable: true
    sort_key-2:
      type: string
      nullable: true
    archived_at:
      type: string
      format: date-time
      nullable: true
    DocumentUser:
      type: object
      required:
      - id
      - name
      - avatar_url
      properties:
        id:
          type: integer
        name:
          type: string
          nullable: true
        avatar_url:
          type: string
          nullable: true
    DocumentSummary:
      type: object
      required:
      - id
      - workspace_id
      - slug
      - title
      - icon
      - parent_id
      - sort_key
      - archived_at
      - is_public
      - is_workspace_public
      - is_draft
      - updated_at
      - updated_by
      - comments_count
      - open_threads_count
      properties:
        id:
          type: integer
        workspace_id:
          type: integer
        slug:
          "$ref": "#/components/schemas/slug-2"
        title:
          type: string
        icon:
          type: string
          nullable: true
          maxLength: 16
        parent_id:
          "$ref": "#/components/schemas/parent_id-2"
        sort_key:
          "$ref": "#/components/schemas/sort_key-2"
        archived_at:
          "$ref": "#/components/schemas/archived_at"
        is_public:
          "$ref": "#/components/schemas/is_public"
        is_workspace_public:
          "$ref": "#/components/schemas/is_workspace_public"
        is_draft:
          "$ref": "#/components/schemas/is_draft"
        updated_at:
          type: string
          format: date-time
        updated_by:
          allOf:
          - "$ref": "#/components/schemas/DocumentUser"
          type: object
          nullable: true
        comments_count:
          type: integer
        open_threads_count:
          type: integer
        excerpt:
          type: string
      example:
        id: 45
        workspace_id: 34
        slug: release-plan
        title: Release plan
        icon: "\U0001F680"
        parent_id: 12
        sort_key: a1
        archived_at:
        is_public: false
        is_workspace_public: true
        is_draft: true
        updated_at: '2026-10-04T19:51:17.480-03:00'
        updated_by:
          id: 7
          name: Ana
          avatar_url:
        comments_count: 3
        open_threads_count: 1
    DocumentCreateRequest:
      type: object
      properties:
        workspace_document:
          type: object
          properties:
            title:
              type: string
            body:
              type: string
              nullable: true
            icon:
              type: string
              nullable: true
              maxLength: 16
            parent_id:
              type: integer
              nullable: true
            after_id:
              type: integer
            sort_key:
              type: string
            is_workspace_public:
              "$ref": "#/components/schemas/is_workspace_public"
            is_public:
              "$ref": "#/components/schemas/is_public"
            is_draft:
              "$ref": "#/components/schemas/is_draft"
      example:
        workspace_document:
          title: Release plan
          icon: "\U0001F680"
          parent_id: 12
          after_id: 44
          body: ''
    lock_version:
      type: integer
      default: 0
    DocumentBreadcrumb:
      type: object
      required:
      - id
      - slug
      - title
      - icon
      properties:
        id:
          type: integer
        slug:
          type: string
        title:
          type: string
        icon:
          type: string
          nullable: true
    SharedDocument:
      allOf:
      - "$ref": "#/components/schemas/DocumentSummary"
      - type: object
        required:
        - body
        - lock_version
        - created_at
        - created_by
        - breadcrumbs
        - public_url
        properties:
          body:
            type: string
            nullable: true
          lock_version:
            "$ref": "#/components/schemas/lock_version"
          created_at:
            type: string
            format: date-time
          created_by:
            allOf:
            - "$ref": "#/components/schemas/DocumentUser"
            type: object
            nullable: true
          breadcrumbs:
            type: array
            items:
              "$ref": "#/components/schemas/DocumentBreadcrumb"
          public_url:
            type: string
            nullable: true
            example: https://ontrama.com/share/documents/JVjosY1HUp0P_Pcr7gKJMJeis8wtB7t7
    Backlink:
      type: object
      required:
      - type
      - id
      - title
      - url
      properties:
        type:
          type: string
          enum:
          - task
          - document
        id:
          type: integer
        title:
          type: string
        url:
          type: string
          example: "/tasks/123"
        issue_key:
          type: string
          nullable: true
        board_id:
          type: integer
        board_name:
          type: string
        is_done:
          type: boolean
        icon:
          type: string
          nullable: true
    DocumentPermissions:
      type: object
      required:
      - can_edit
      - can_comment
      - can_manage
      properties:
        can_edit:
          type: boolean
        can_comment:
          type: boolean
        can_manage:
          type: boolean
    Document:
      allOf:
      - "$ref": "#/components/schemas/SharedDocument"
      - type: object
        required:
        - children
        - backlinks
        - permissions
        properties:
          children:
            type: array
            items:
              "$ref": "#/components/schemas/DocumentSummary"
          backlinks:
            type: array
            items:
              "$ref": "#/components/schemas/Backlink"
          permissions:
            "$ref": "#/components/schemas/DocumentPermissions"
      example:
        id: 45
        workspace_id: 34
        slug: release-plan
        title: Release plan
        icon: "\U0001F680"
        parent_id: 12
        sort_key: a1
        archived_at:
        is_public: false
        is_workspace_public: true
        is_draft: true
        updated_at: '2026-10-04T19:51:17.480-03:00'
        updated_by:
          id: 7
          name: Ana
          avatar_url:
        comments_count: 3
        open_threads_count: 1
        body: |-
          # v2

          Ships with [PROJ-12 Fix the login](/tasks/123). Owner: [@ id="7" label="Ana"]
        lock_version: 4
        created_at: '2026-10-01T10:00:00.000-03:00'
        created_by:
          id: 7
          name: Ana
          avatar_url:
        breadcrumbs:
        - id: 12
          slug: product
          title: Product
          icon: "\U0001F4E6"
        public_url:
        children: []
        backlinks:
        - type: task
          id: 123
          title: Fix the login
          issue_key: PROJ-12
          board_id: 41
          board_name: Product
          is_done: false
          url: "/tasks/123"
        - type: document
          id: 50
          title: Retro
          icon:
          url: "/documents/50"
        permissions:
          can_edit: true
          can_comment: true
          can_manage: false
    PlacementError:
      type: object
      additionalProperties:
        type: array
        items:
          type: string
      example:
        after_id:
        - must be a sibling of the document
    DocumentUpdateRequest:
      type: object
      properties:
        workspace_document:
          type: object
          properties:
            title:
              type: string
            body:
              type: string
              nullable: true
            icon:
              type: string
              nullable: true
              maxLength: 16
            lock_version:
              type: integer
            parent_id:
              type: integer
              nullable: true
            after_id:
              type: integer
            sort_key:
              type: string
            is_workspace_public:
              "$ref": "#/components/schemas/is_workspace_public"
            is_public:
              "$ref": "#/components/schemas/is_public"
            is_draft:
              "$ref": "#/components/schemas/is_draft"
      example:
        workspace_document:
          body: |-
            # v2

            Ships with [PROJ-12 Fix the login](/tasks/123).
          lock_version: 4
    DocumentConflict:
      type: object
      required:
      - error
      - document
      properties:
        error:
          type: string
          enum:
          - conflict
        document:
          "$ref": "#/components/schemas/Document"
    DocumentComment:
      type: object
      required:
      - id
      - workspace_document_id
      - body
      - anchor_text
      - user
      - parent_id
      - resolved_at
      - resolved_by
      - edited_at
      - created_at
      - updated_at
      properties:
        id:
          type: integer
        workspace_document_id:
          type: integer
        body:
          type: string
        anchor_text:
          type: string
          nullable: true
        user:
          "$ref": "#/components/schemas/DocumentUser"
        parent_id:
          type: integer
          nullable: true
        resolved_at:
          type: string
          format: date-time
          nullable: true
        resolved_by:
          allOf:
          - "$ref": "#/components/schemas/DocumentUser"
          type: object
          nullable: true
        edited_at:
          type: string
          format: date-time
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      example:
        id: 9
        workspace_document_id: 45
        body: Should this wait for [PROJ-12](/tasks/123)?
        anchor_text: Ships with PROJ-12
        user:
          id: 8
          name: Bruno
          avatar_url:
        parent_id:
        resolved_at:
        resolved_by:
        edited_at:
        created_at: '2026-10-04T19:51:17.291-03:00'
        updated_at: '2026-10-04T19:51:17.291-03:00'
    DocumentThread:
      allOf:
      - "$ref": "#/components/schemas/DocumentComment"
      - type: object
        required:
        - replies
        properties:
          replies:
            type: array
            items:
              "$ref": "#/components/schemas/DocumentComment"
    DocumentCommentCreateRequest:
      type: object
      required:
      - body
      properties:
        body:
          type: string
        parent_id:
          type: integer
          nullable: true
        anchor_text:
          type: string
          nullable: true
      example:
        body: Should this wait for [PROJ-12](/tasks/123)?
        anchor_text: Ships with PROJ-12
    DocumentCommentUpdateRequest:
      type: object
      required:
      - body
      properties:
        body:
          type: string
      example:
        body: Should this wait for [PROJ-12](/tasks/123)? (edited)
    WorkspaceUser:
      type: object
      properties:
        id:
          type: integer
        role:
          "$ref": "#/components/schemas/role-2"
        user:
          "$ref": "#/components/schemas/UserSummary"
    MessageResponse:
      type: object
      required:
      - message
      properties:
        message:
          type: string
    WorkspaceUserRoleInput:
      type: object
      properties:
        workspace_user:
          type: object
          properties:
            role:
              type: string
              enum:
              - role_member
              - role_admin
              - role_viewer
    archived:
      type: boolean
      default: false
    BoardListItemMember:
      type: object
      properties:
        id:
          type: integer
        role:
          "$ref": "#/components/schemas/role"
        name:
          type: string
          nullable: true
        avatar_url:
          type: string
          nullable: true
        email:
          type: string
          format: email
        is_owner:
          type: boolean
    BoardListItem:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        archived:
          "$ref": "#/components/schemas/archived"
        visibility:
          "$ref": "#/components/schemas/visibility"
        board_columns_count:
          type: integer
        tasks_count:
          type: integer
        board_users_count:
          type: integer
        current_user_role:
          type: string
          nullable: true
          enum:
          - role_viewer
          - role_member
          - role_admin
          - role_owner
          -
        board_users:
          type: array
          items:
            "$ref": "#/components/schemas/BoardListItemMember"
        workspace:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
            slug:
              type: string
      example:
        id: 41
        name: Lixta roadmap
        created_at: '2026-03-27T23:42:03.374-03:00'
        updated_at: '2026-07-04T18:43:41.717-03:00'
        archived: false
        visibility: visibility_workspace
        board_columns_count: 4
        tasks_count: 318
        board_users_count: 1
        current_user_role: role_owner
        board_users:
        - id: 1
          role: role_owner
          email: ana@example.com
          name: Ana
          avatar_url:
          is_owner: true
        workspace:
          id: 34
          name: Pixta
          slug: pixta
    BoardCreateRequest:
      type: object
      properties:
        name:
          type: string
        workspace_id:
          oneOf:
          - type: integer
          - type: string
        board:
          type: object
          required:
          - workspace_id
          properties:
            name:
              type: string
            workspace_id:
              oneOf:
              - type: integer
              - type: string
            visibility:
              type: string
              enum:
              - visibility_private
              - visibility_workspace
              - visibility_public
            time_tracking_enabled:
              type: boolean
            description:
              type: string
            todo_board_column_id:
              type: integer
              nullable: true
            done_board_column_id:
              type: integer
              nullable: true
            in_review_board_column_id:
              type: integer
              nullable: true
      example:
        board:
          name: Lixta roadmap
          workspace_id: pixta
    time_tracking_enabled:
      type: boolean
      default: true
    todo_board_column_id:
      type: integer
      nullable: true
      default:
    done_board_column_id:
      type: integer
      nullable: true
      default:
    in_review_board_column_id:
      type: integer
      nullable: true
      default:
    BoardTemplateChecklist:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
          nullable: true
        task_check_items_count:
          type: integer
    BoardTemplate:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
          nullable: true
        body:
          type: string
          nullable: true
        board_column_id:
          type: integer
        tags:
          type: array
          items:
            "$ref": "#/components/schemas/Tag"
        is_template:
          type: boolean
          enum:
          - true
        priority:
          type: string
          enum:
          - priority_none
          - priority_low
          - priority_medium
          - priority_high
          - priority_urgent
        issue_number:
          type: integer
          nullable: true
        due_at:
          type: string
          format: date-time
          nullable: true
        start_at:
          type: string
          format: date-time
          nullable: true
        milestone_id:
          type: integer
          nullable: true
        issue_key:
          type: string
          nullable: true
        task_checklists:
          type: array
          items:
            "$ref": "#/components/schemas/BoardTemplateChecklist"
    BoardMilestone:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        description:
          type: string
          nullable: true
        target_date:
          type: string
          format: date-time
          nullable: true
        position:
          type: integer
    MilestoneSummary:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        target_date:
          type: string
          format: date-time
          nullable: true
        position:
          type: integer
    TaskAssignee:
      type: object
      properties:
        role:
          type: string
          enum:
          - role_member
        id:
          type: integer
        email:
          type: string
          format: email
        name:
          type: string
          nullable: true
        avatar_url:
          type: string
          nullable: true
    TaskActivity:
      type: object
      required:
      - id
      - activity_type
      - data
      - body
      - parent_id
      - edited_at
      - created_at
      - updated_at
      - image_preview_url
      - user
      properties:
        id:
          type: integer
        parent_id:
          type: integer
          nullable: true
        edited_at:
          type: string
          format: date-time
          nullable: true
        activity_type:
          "$ref": "#/components/schemas/activity_type"
        data:
          type: object
          additionalProperties: true
        body:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        image_preview_url:
          type: string
          nullable: true
        user:
          "$ref": "#/components/schemas/UserSummary"
    TaskCheckItem:
      type: object
      required:
      - id
      - name
      - is_complete
      - created_at
      - updated_at
      properties:
        id:
          type: integer
        name:
          type: string
          nullable: true
        is_complete:
          type: boolean
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    TaskChecklist:
      type: object
      required:
      - id
      - name
      - created_at
      - updated_at
      - task_check_items
      properties:
        id:
          type: integer
        name:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        task_check_items:
          type: array
          items:
            "$ref": "#/components/schemas/TaskCheckItem"
    BoardTaskCard:
      allOf:
      - type: object
        properties:
          id:
            type: integer
          name:
            type: string
            nullable: true
          body:
            type: string
            nullable: true
          board_column_id:
            type: integer
          created_at:
            type: string
            format: date-time
          updated_at:
            type: string
            format: date-time
          tags:
            type: array
            items:
              "$ref": "#/components/schemas/Tag"
          stopwatch_elapsed_seconds:
            type: integer
            nullable: true
          stopwatch_started_at:
            type: string
            format: date-time
            nullable: true
          due_at:
            type: string
            format: date-time
            nullable: true
          start_at:
            type: string
            format: date-time
            nullable: true
          sort_key:
            type: string
            nullable: true
          archived:
            type: boolean
          is_template:
            type: boolean
            enum:
            - false
          priority:
            type: string
            enum:
            - priority_none
            - priority_low
            - priority_medium
            - priority_high
            - priority_urgent
          issue_number:
            type: integer
            nullable: true
          milestone_id:
            type: integer
            nullable: true
          issue_key:
            type: string
            nullable: true
            example: BOARDP-1377
          position:
            type: integer
            nullable: true
          milestone:
            "$ref": "#/components/schemas/MilestoneSummary"
          task_users:
            type: array
            items:
              "$ref": "#/components/schemas/TaskAssignee"
          task_activities:
            type: array
            items:
              "$ref": "#/components/schemas/TaskActivity"
          task_checklists:
            type: array
            items:
              "$ref": "#/components/schemas/TaskChecklist"
      - "$ref": "#/components/schemas/CardRelations"
      example:
        id: 7104
        name: Fix login redirect
        body: "<p>Steps to reproduce…</p>"
        board_column_id: 29
        created_at: '2026-09-30T10:12:40.775-03:00'
        updated_at: '2026-10-01T08:00:00.000-03:00'
        tags: []
        stopwatch_elapsed_seconds: 0
        stopwatch_started_at:
        due_at:
        start_at:
        sort_key: a1
        archived: false
        is_template: false
        priority: priority_high
        issue_number: 1377
        milestone_id:
        parent_id:
        issue_key: BOARDP-1377
        position: 0
        parent_issue_key:
        sub_issues_progress:
          completed: 0
          total: 0
        blocked: false
        blocks_count: 0
        is_done: false
        pull_requests: []
        task_users: []
        task_activities: []
        task_checklists: []
    BoardColumn:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        color:
          type: string
          nullable: true
        position:
          type: integer
        tasks:
          type: array
          items:
            "$ref": "#/components/schemas/BoardTaskCard"
    Board:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        archived:
          "$ref": "#/components/schemas/archived"
        visibility:
          "$ref": "#/components/schemas/visibility"
        time_tracking_enabled:
          "$ref": "#/components/schemas/time_tracking_enabled"
        description:
          type: string
          nullable: true
        todo_board_column_id:
          "$ref": "#/components/schemas/todo_board_column_id"
        done_board_column_id:
          "$ref": "#/components/schemas/done_board_column_id"
        in_review_board_column_id:
          "$ref": "#/components/schemas/in_review_board_column_id"
        workspace:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
            slug:
              type: string
            issue_prefix:
              type: string
              nullable: true
              example: BOARDP
        templates:
          type: array
          items:
            "$ref": "#/components/schemas/BoardTemplate"
        milestones:
          type: array
          items:
            "$ref": "#/components/schemas/BoardMilestone"
        board_columns:
          type: array
          items:
            "$ref": "#/components/schemas/BoardColumn"
      example:
        id: 41
        name: Lixta roadmap
        created_at: '2026-03-27T23:42:03.374-03:00'
        updated_at: '2026-07-04T18:43:41.717-03:00'
        archived: false
        visibility: visibility_private
        time_tracking_enabled: true
        description:
        todo_board_column_id: 28
        done_board_column_id: 31
        in_review_board_column_id:
        workspace:
          id: 34
          name: Pixta
          slug: pixta
          issue_prefix: BOARDP
        templates: []
        milestones:
        - id: 3
          name: Beta
          description:
          target_date: '2026-11-30T23:59:59.999-03:00'
          position: 0
        board_columns:
        - id: 28
          name: To do
          created_at: '2026-03-27T23:42:03.374-03:00'
          updated_at: '2026-03-27T23:42:03.374-03:00'
          color:
          position: 0
          tasks: []
    StatusError-2:
      type: object
      properties:
        status:
          type: integer
        error:
          type: string
      example:
        status: 500
        error: Internal Server Error
    BoardColumnRequest:
      type: object
      properties:
        board_column:
          type: object
          properties:
            name:
              type: string
            position:
              type: integer
            color:
              type: string
              nullable: true
        name:
          type: string
        position:
          type: integer
        color:
          type: string
          nullable: true
      example:
        name: Unnamed column
    BoardColumnTaskCard:
      allOf:
      - type: object
        properties:
          id:
            type: integer
          name:
            type: string
            nullable: true
          body:
            type: string
            nullable: true
          board_column_id:
            type: integer
          created_at:
            type: string
            format: date-time
          updated_at:
            type: string
            format: date-time
          tags:
            type: array
            items:
              "$ref": "#/components/schemas/Tag"
          stopwatch_elapsed_seconds:
            type: integer
            nullable: true
          stopwatch_started_at:
            type: string
            format: date-time
            nullable: true
          due_at:
            type: string
            format: date-time
            nullable: true
          sort_key:
            type: string
            nullable: true
          is_template:
            type: boolean
            enum:
            - false
          priority:
            type: string
            enum:
            - priority_none
            - priority_low
            - priority_medium
            - priority_high
            - priority_urgent
          issue_number:
            type: integer
            nullable: true
          issue_key:
            type: string
            nullable: true
          position:
            type: integer
            nullable: true
          task_users:
            type: array
            items:
              "$ref": "#/components/schemas/TaskAssignee"
          task_activities:
            type: array
            items:
              "$ref": "#/components/schemas/TaskActivity"
          task_checklists:
            type: array
            items:
              "$ref": "#/components/schemas/TaskChecklist"
      - "$ref": "#/components/schemas/CardRelations"
    BoardColumnDetail:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        color:
          type: string
          nullable: true
        position:
          type: integer
        tasks:
          type: array
          items:
            "$ref": "#/components/schemas/BoardColumnTaskCard"
      example:
        id: 32
        name: Unnamed column
        created_at: '2026-10-04T12:00:00.000-03:00'
        updated_at: '2026-10-04T12:00:00.000-03:00'
        color:
        position: 0
        tasks: []
    MoveAllTasksRequest:
      type: object
      required:
      - to_board_id
      - to_column_id
      properties:
        to_board_id:
          oneOf:
          - type: integer
          - type: string
        to_column_id:
          oneOf:
          - type: integer
          - type: string
      example:
        to_board_id: '42'
        to_column_id: '57'
    BoardUser:
      type: object
      properties:
        id:
          type: integer
        role:
          "$ref": "#/components/schemas/role"
        is_owner:
          type: boolean
        user:
          "$ref": "#/components/schemas/UserSummary"
      example:
        id: 88
        role: role_member
        is_owner: false
        user:
          id: 7
          email: bruno@example.com
          name: Bruno
          avatar_url:
    BoardUserUpdateRequest:
      type: object
      required:
      - board_user
      properties:
        board_user:
          type: object
          required:
          - role
          properties:
            role:
              type: string
              enum:
              - role_viewer
              - role_member
              - role_admin
      example:
        board_user:
          role: role_admin
    OkMessage:
      type: object
      properties:
        message:
          type: string
          enum:
          - ok
    Milestone:
      type: object
      properties:
        id:
          type: integer
        board_id:
          type: integer
        name:
          type: string
        description:
          type: string
          nullable: true
        target_date:
          type: string
          format: date-time
          nullable: true
        position:
          type: integer
          minimum: 0
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        tasks_count:
          type: integer
      example:
        id: 3
        board_id: 41
        name: Beta
        description:
        target_date: '2026-11-30T23:59:59.999-03:00'
        position: 0
        created_at: '2026-09-01T10:00:00.000-03:00'
        updated_at: '2026-09-01T10:00:00.000-03:00'
        tasks_count: 12
    MilestoneRequest:
      type: object
      required:
      - milestone
      properties:
        milestone:
          type: object
          properties:
            name:
              type: string
            description:
              type: string
              nullable: true
            target_date:
              type: string
              format: date-time
              nullable: true
            position:
              type: integer
              minimum: 0
      example:
        milestone:
          name: Beta
          target_date: '2026-11-30T23:59:59.999Z'
    TagListItem:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
          nullable: true
        color:
          type: string
          nullable: true
    TagRequest:
      type: object
      required:
      - tag
      properties:
        tag:
          type: object
          properties:
            name:
              type: string
            color:
              type: string
            board_id:
              oneOf:
              - type: integer
              - type: string
      example:
        tag:
          name: backend
          color: "#3b82f6"
    TagShow:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
          nullable: true
        color:
          type: string
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    BoardUpdateRequest:
      type: object
      properties:
        name:
          type: string
        id:
          type: integer
        board:
          type: object
          properties:
            name:
              type: string
            visibility:
              type: string
              enum:
              - visibility_private
              - visibility_workspace
              - visibility_public
            time_tracking_enabled:
              type: boolean
            description:
              type: string
              nullable: true
            todo_board_column_id:
              type: integer
              nullable: true
            done_board_column_id:
              type: integer
              nullable: true
            in_review_board_column_id:
              type: integer
              nullable: true
      example:
        board:
          time_tracking_enabled: true
          description: Product roadmap
          todo_board_column_id: 28
          done_board_column_id: 31
          in_review_board_column_id:
    ShareRequest:
      type: object
      required:
      - email
      properties:
        email:
          type: string
          format: email
      example:
        email: bruno@example.com
    PositionsRequest:
      type: object
      required:
      - positions
      properties:
        positions:
          type: array
          items:
            type: object
            required:
            - id
            - position
            properties:
              id:
                type: integer
              position:
                type: integer
      example:
        positions:
        - id: 28
          position: 0
        - id: 31
          position: 1
    TaskAttributes:
      type: object
      properties:
        name:
          type: string
          example: Fix login redirect
        position:
          type: integer
        body:
          type: string
        board_column_id:
          type: integer
        due_at:
          type: string
          format: date-time
          nullable: true
        start_at:
          type: string
          format: date-time
          nullable: true
        sort_key:
          type: string
          nullable: true
        is_template:
          type: boolean
        priority:
          type: string
          enum:
          - priority_none
          - priority_low
          - priority_medium
          - priority_high
          - priority_urgent
        milestone_id:
          type: integer
          nullable: true
        parent_id:
          type: integer
          nullable: true
    TaskCreateRequest:
      type: object
      properties:
        task:
          "$ref": "#/components/schemas/TaskAttributes"
        template_id:
          type: integer
        insert_after_task_id:
          type: integer
        board_column_id:
          type: integer
      example:
        task:
          board_column_id: 310
          name: Fix login redirect
          body: "<p>Users land on /404 after OTP. Related to BOARDP-1200.</p>"
          priority: priority_high
          due_at: '2026-10-10T18:00:00.000-03:00'
          parent_id: 7001
        insert_after_task_id: 7090
    stopwatch_started_at:
      type: string
      format: date-time
      nullable: true
    due_at:
      type: string
      format: date-time
      nullable: true
    start_at:
      type: string
      format: date-time
      nullable: true
    is_template:
      type: boolean
      default: false
    archived-2:
      type: boolean
      default: false
    milestone_id:
      type: integer
      nullable: true
    is_complete:
      type: boolean
      default: false
    sub_issue_sort_key:
      type: string
      nullable: true
    PickerItem:
      type: object
      required:
      - id
      - name
      - board_id
      - board_column_id
      - priority
      - issue_number
      - parent_id
      - archived
      - is_complete
      - issue_key
      - is_done
      - column_name
      - column_color
      - sub_issue_sort_key
      - task_users
      properties:
        id:
          type: integer
          example: 7105
        name:
          type: string
          nullable: true
          example: Add OAuth consent screen
        board_id:
          type: integer
          example: 41
        board_column_id:
          type: integer
          example: 311
        priority:
          "$ref": "#/components/schemas/priority"
        issue_number:
          "$ref": "#/components/schemas/issue_number"
        parent_id:
          "$ref": "#/components/schemas/parent_id"
        archived:
          "$ref": "#/components/schemas/archived-2"
        is_complete:
          "$ref": "#/components/schemas/is_complete"
        issue_key:
          type: string
          nullable: true
          example: BOARDP-1378
        is_done:
          "$ref": "#/components/schemas/is_done"
        column_name:
          type: string
          nullable: true
          example: In progress
        column_color:
          type: string
          nullable: true
        sub_issue_sort_key:
          "$ref": "#/components/schemas/sub_issue_sort_key"
        task_users:
          type: array
          items:
            "$ref": "#/components/schemas/TaskAssignee"
    IssueRef:
      allOf:
      - "$ref": "#/components/schemas/PickerItem"
      - type: object
        properties:
          relation_id:
            type: integer
          relation_type:
            type: string
            enum:
            - blocked_by
            - blocks
            - related
            - duplicate_of
            - duplicates
    TaskRelations:
      type: object
      required:
      - blocked_by
      - blocks
      - related
      - duplicate_of
      - duplicates
      properties:
        blocked_by:
          type: array
          items:
            "$ref": "#/components/schemas/IssueRef"
        blocks:
          type: array
          items:
            "$ref": "#/components/schemas/IssueRef"
        related:
          type: array
          items:
            "$ref": "#/components/schemas/IssueRef"
        duplicate_of:
          type: object
          allOf:
          - "$ref": "#/components/schemas/IssueRef"
          nullable: true
        duplicates:
          type: array
          items:
            "$ref": "#/components/schemas/IssueRef"
    PullRequest:
      type: object
      properties:
        id:
          type: integer
        provider:
          "$ref": "#/components/schemas/provider"
        host:
          type: string
          example: github.com
        repository:
          type: string
          example: locomotiva/tarefas-backend
        number:
          type: integer
          example: 42
        external_id:
          type: string
          nullable: true
        url:
          type: string
          example: https://github.com/locomotiva/tarefas-backend/pull/42
        title:
          type: string
          nullable: true
        status:
          "$ref": "#/components/schemas/status"
        review_state:
          "$ref": "#/components/schemas/review_state"
        ci_status:
          "$ref": "#/components/schemas/ci_status"
        branch_name:
          type: string
          nullable: true
        opened_at:
          type: string
          format: date-time
          nullable: true
        merged_at:
          type: string
          format: date-time
          nullable: true
        closed_at:
          type: string
          format: date-time
          nullable: true
        display_ref:
          type: string
          example: "#42"
    Task:
      type: object
      required:
      - id
      - name
      - position
      - body
      - board_id
      - board_column_id
      - tags
      - stopwatch_elapsed_seconds
      - stopwatch_started_at
      - due_at
      - start_at
      - sort_key
      - is_template
      - priority
      - archived
      - issue_number
      - milestone_id
      - parent_id
      - issue_key
      - is_done
      - task_users
      - task_activities
      - task_checklists
      - parent
      - sub_issues
      - sub_issues_progress
      - relations
      - blocked
      - blocks_count
      - pull_requests
      properties:
        backlinks:
          type: array
          items:
            "$ref": "#/components/schemas/Backlink"
        id:
          type: integer
          example: 7104
        name:
          type: string
          nullable: true
          example: Fix login redirect
        position:
          type: integer
        body:
          type: string
          nullable: true
        board_id:
          type: integer
          example: 41
        board_column_id:
          type: integer
          example: 310
        tags:
          type: array
          items:
            "$ref": "#/components/schemas/Tag"
        stopwatch_elapsed_seconds:
          type: integer
        stopwatch_started_at:
          "$ref": "#/components/schemas/stopwatch_started_at"
        due_at:
          "$ref": "#/components/schemas/due_at"
        start_at:
          "$ref": "#/components/schemas/start_at"
        sort_key:
          "$ref": "#/components/schemas/sort_key"
        is_template:
          "$ref": "#/components/schemas/is_template"
        priority:
          "$ref": "#/components/schemas/priority"
        archived:
          "$ref": "#/components/schemas/archived-2"
        issue_number:
          "$ref": "#/components/schemas/issue_number"
        milestone_id:
          "$ref": "#/components/schemas/milestone_id"
        parent_id:
          "$ref": "#/components/schemas/parent_id"
        issue_key:
          type: string
          nullable: true
          example: BOARDP-1377
        is_done:
          "$ref": "#/components/schemas/is_done"
        milestone:
          allOf:
          - "$ref": "#/components/schemas/MilestoneSummary"
        task_users:
          type: array
          items:
            "$ref": "#/components/schemas/TaskAssignee"
        task_activities:
          type: array
          items:
            "$ref": "#/components/schemas/TaskActivity"
        task_checklists:
          type: array
          items:
            "$ref": "#/components/schemas/TaskChecklist"
        parent:
          type: object
          allOf:
          - "$ref": "#/components/schemas/IssueRef"
          nullable: true
        sub_issues:
          type: array
          items:
            "$ref": "#/components/schemas/IssueRef"
        sub_issues_progress:
          "$ref": "#/components/schemas/SubIssuesProgress"
        relations:
          "$ref": "#/components/schemas/TaskRelations"
        blocked:
          "$ref": "#/components/schemas/blocked"
        blocks_count:
          type: integer
        pull_requests:
          type: array
          items:
            "$ref": "#/components/schemas/PullRequest"
    TaskUpdateRequest:
      type: object
      properties:
        task:
          "$ref": "#/components/schemas/TaskAttributes"
        board_column_id:
          type: integer
        insert_after_task_id:
          type: integer
      example:
        task:
          sort_key: a0V
          board_column_id: 311
    TaskAttachmentRequest:
      type: object
      properties:
        body:
          type: string
      example:
        body: https://s3.sa-east-1.amazonaws.com/lixtame-public/uploads/screenshot_c697c417.png
    TaskMoveRequest:
      type: object
      required:
      - to_board_id
      - to_column_id
      properties:
        to_board_id:
          type: integer
        to_column_id:
          type: integer
        insert_after_task_id:
          type: integer
      example:
        to_board_id: 41
        to_column_id: 312
        insert_after_task_id: 7090
    TaskMoveInvalid:
      type: object
      properties:
        errors:
          "$ref": "#/components/schemas/ValidationErrors"
      example:
        errors:
          start_at:
          - must be on or before due date
    SubIssuesReorderRequest:
      type: object
      properties:
        ordered_ids:
          type: array
          items:
            type: integer
        ids:
          type: array
          items:
            type: integer
      example:
        ordered_ids:
        - 7110
        - 7108
        - 7109
    TaskTaggingsRequest:
      type: object
      properties:
        tag_ids:
          type: array
          nullable: true
          items:
            type: integer
      example:
        tag_ids:
        - 12
        - 15
    TaskUsersRequest:
      type: object
      required:
      - user_ids
      properties:
        user_ids:
          type: array
          items:
            type: integer
      example:
        user_ids:
        - 1
        - 265
    CommentCreateRequest:
      type: object
      properties:
        parent_id:
          type: integer
          nullable: true
        body:
          type: string
      example:
        body: <p>[@ id="265" label="Bruno Netto"] can you check BOARDP-1200?</p>
    TaskRelationCreateRequest:
      type: object
      properties:
        related_task_id:
          oneOf:
          - type: integer
          - type: string
        to_task_id:
          oneOf:
          - type: integer
          - type: string
        relation_type:
          type: string
          enum:
          - related
          - blocks
          - blocked_by
          - duplicate
          - duplicate_of
          default: related
      example:
        related_task_id: BOARDP-1200
        relation_type: blocked_by
    TaskErrorList:
      type: object
      properties:
        errors:
          type: array
          items:
            type: string
      example:
        errors:
        - issues cannot block each other
    SubIssuesCreateRequest:
      type: object
      properties:
        name:
          type: string
        names:
          type: array
          items:
            type: string
        body:
          type: string
        existing_task_id:
          oneOf:
          - type: integer
          - type: string
        existing_task_ids:
          type: array
          items:
            oneOf:
            - type: integer
            - type: string
      example:
        names:
        - "- Write migration"
        - "- Backfill data"
    TaskCheckItemRequest:
      type: object
      required:
      - task_check_item
      properties:
        task_check_item:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
            is_complete:
              type: boolean
            task_checklist_id:
              type: integer
            position:
              type: integer
            _destroy:
              oneOf:
              - type: boolean
              - type: string
      example:
        task_check_item:
          task_checklist_id: 912
          name: Write migration
    TaskCheckItemRecord:
      type: object
      properties:
        id:
          type: integer
        task_checklist_id:
          type: integer
        name:
          type: string
          nullable: true
        position:
          type: integer
        is_complete:
          type: boolean
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      example:
        id: 5521
        task_checklist_id: 912
        name: Write migration
        position: 0
        is_complete: false
        created_at: '2026-10-04T12:00:00.000-03:00'
        updated_at: '2026-10-04T12:00:00.000-03:00'
    BadRequest:
      type: object
      properties:
        status:
          type: integer
          example: 400
        error:
          type: string
          example: Bad Request
    TaskChecklistRequest:
      type: object
      properties:
        task_checklist:
          type: object
          properties:
            name:
              type: string
            position:
              type: integer
        name:
          type: string
        position:
          type: integer
        id:
          type: integer
        _destroy:
          oneOf:
          - type: boolean
          - type: string
      example:
        name: New Checklist
    TaskChecklistRecord:
      type: object
      properties:
        id:
          type: integer
        task_id:
          type: integer
        name:
          type: string
          nullable: true
        position:
          type: integer
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      example:
        id: 912
        task_id: 7104
        name: New Checklist
        position: 0
        created_at: '2026-10-04T12:00:00.000-03:00'
        updated_at: '2026-10-04T12:00:00.000-03:00'
    TaskLookup:
      type: object
      required:
      - id
      - board_id
      properties:
        id:
          type: integer
        board_id:
          type: integer
        issue_key:
          type: string
          nullable: true
        workspace_slug:
          type: string
          nullable: true
      example:
        id: 123
        board_id: 41
        issue_key: PROJ-12
        workspace_slug: acme
    PullRequestLinkRequest:
      type: object
      properties:
        url:
          type: string
        provider:
          type: string
          example: github
        repository:
          type: string
          example: locomotiva/tarefas-backend
        number:
          oneOf:
          - type: integer
          - type: string
        host:
          type: string
        title:
          type: string
        status:
          type: string
    ErrorList:
      type: object
      properties:
        errors:
          type: array
          items:
            type: string
      example:
        errors:
        - Provider is not included in the list
    provider-2:
      type: string
      enum:
      - github
      - gitlab
    host:
      type: string
      default: github.com
    installation_id:
      type: string
      nullable: true
    ConnectedBy:
      type: object
      nullable: true
      properties:
        id:
          type: integer
        email:
          type: string
          format: email
        name:
          type: string
          nullable: true
    GitConnection:
      type: object
      properties:
        id:
          type: integer
        provider:
          "$ref": "#/components/schemas/provider-2"
        host:
          "$ref": "#/components/schemas/host"
        installation_id:
          "$ref": "#/components/schemas/installation_id"
        account_login:
          type: string
          nullable: true
        account_name:
          type: string
          nullable: true
        configured:
          type: boolean
        connected_by:
          "$ref": "#/components/schemas/ConnectedBy"
        repositories_count:
          type: integer
        created_at:
          type: string
          format: date-time
    guild_id:
      type: string
    channel_id:
      type: string
    board_id:
      type: integer
    notify_events:
      type: array
      items:
        type: string
        enum:
        - created
        - moved
        - commented
        - assigned
        - archived
      default:
      - created
      - moved
      - commented
      - assigned
      - archived
    GrupimConnection:
      type: object
      properties:
        id:
          type: integer
        guild_id:
          "$ref": "#/components/schemas/guild_id"
        guild_name:
          type: string
          nullable: true
        channel_id:
          "$ref": "#/components/schemas/channel_id"
        channel_name:
          type: string
          nullable: true
        board_id:
          "$ref": "#/components/schemas/board_id"
        board_name:
          type: string
          nullable: true
        notify_events:
          "$ref": "#/components/schemas/notify_events"
        connected_by:
          "$ref": "#/components/schemas/ConnectedBy"
        members_count:
          type: integer
        created_at:
          type: string
          format: date-time
    IntegrationsIndex:
      type: object
      properties:
        github_configured:
          type: boolean
        gitlab_configured:
          type: boolean
        grupim_configured:
          type: boolean
        connections:
          type: array
          items:
            "$ref": "#/components/schemas/GitConnection"
        grupim:
          type: object
          allOf:
          - "$ref": "#/components/schemas/GrupimConnection"
          nullable: true
    UrlResponse:
      type: object
      required:
      - url
      properties:
        url:
          type: string
    GrupimConnectionCreateRequest:
      type: object
      required:
      - code
      - board_id
      properties:
        code:
          type: string
          example: ABCD-EFGH-JKLM
        channel_id:
          type: string
        board_id:
          type: integer
        notify_events:
          type: array
          items:
            type: string
            enum:
            - created
            - moved
            - commented
            - assigned
            - archived
    GrupimConnectionEnvelope:
      type: object
      properties:
        connection:
          "$ref": "#/components/schemas/GrupimConnection"
    GrupimConnectionUpdateRequest:
      type: object
      properties:
        board_id:
          type: integer
        channel_id:
          type: string
        notify_events:
          type: array
          items:
            type: string
            enum:
            - created
            - moved
            - commented
            - assigned
            - archived
    GrupimChannel:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        type:
          type: integer
          enum:
          - 0
          - 5
        parent_id:
          type: string
          nullable: true
    GrupimClaimPreview:
      type: object
      properties:
        claim:
          type: object
          properties:
            guild_id:
              type: string
              example: '1291234567890123456'
            guild_name:
              type: string
              nullable: true
              example: Pixta
            channel_id:
              type: string
              nullable: true
            requested_by:
              type: string
              nullable: true
              example: ana
            expires_at:
              type: string
              format: date-time
        channels:
          type: array
          items:
            "$ref": "#/components/schemas/GrupimChannel"
    GrupimLinkPreview:
      type: object
      properties:
        link_code:
          type: object
          properties:
            grupim_user_id:
              type: string
            grupim_username:
              type: string
              nullable: true
            guild_id:
              type: string
            guild_name:
              type: string
              nullable: true
            expires_at:
              type: string
              format: date-time
    GrupimLinkRequest:
      type: object
      required:
      - code
      properties:
        code:
          type: string
          example: aZ3kP9qL0mXw
    GrupimLinkResponse:
      type: object
      properties:
        link:
          type: object
          properties:
            id:
              type: integer
            grupim_user_id:
              type: string
            grupim_username:
              type: string
              nullable: true
            user_id:
              type: integer
            source:
              type: string
              enum:
              - slash
    GrupimMember:
      type: object
      properties:
        grupim_user_id:
          type: string
        username:
          type: string
          nullable: true
        display_name:
          type: string
          nullable: true
        linked:
          type: boolean
        lixta_user:
          type: object
          nullable: true
          properties:
            id:
              type: integer
            email:
              type: string
              format: email
            name:
              type: string
              nullable: true
            username:
              type: string
              nullable: true
            source:
              type: string
              enum:
              - slash
              - admin
              - username_match
    GrupimWorkspaceMember:
      type: object
      properties:
        id:
          type: integer
        email:
          type: string
          format: email
        name:
          type: string
          nullable: true
        username:
          type: string
          nullable: true
        role:
          type: string
          enum:
          - role_member
          - role_admin
          - role_viewer
    GrupimMembersResponse:
      type: object
      properties:
        members:
          type: array
          items:
            "$ref": "#/components/schemas/GrupimMember"
        workspace_members:
          type: array
          items:
            "$ref": "#/components/schemas/GrupimWorkspaceMember"
    GrupimMembersUpdateRequest:
      type: object
      properties:
        match_usernames:
          oneOf:
          - type: boolean
          - type: string
        links:
          type: array
          items:
            type: object
            properties:
              grupim_user_id:
                type: string
              user_id:
                type: integer
                nullable: true
              grupim_username:
                type: string
    enabled:
      type: boolean
      default: true
    webhook_id:
      type: string
      nullable: true
    GitRepository:
      type: object
      properties:
        id:
          type: integer
        external_id:
          type: string
          example: '812345678'
        full_name:
          type: string
          example: locomotiva/tarefas-backend
        html_url:
          type: string
          nullable: true
        enabled:
          "$ref": "#/components/schemas/enabled"
        webhook_id:
          "$ref": "#/components/schemas/webhook_id"
    GitRepositoryList:
      type: object
      properties:
        repositories:
          type: array
          items:
            "$ref": "#/components/schemas/GitRepository"
    GitRepositoriesUpdateRequest:
      type: object
      required:
      - repositories
      properties:
        repositories:
          type: array
          items:
            type: object
            required:
            - external_id
            - enabled
            properties:
              external_id:
                oneOf:
                - type: string
                - type: integer
              enabled:
                oneOf:
                - type: boolean
                - type: string
