Strategic Tickets

Move a ticket to another column, or reorder it inside the one it is in. Name the destination column, then where it goes: position=top or position=bottom, or the two tickets it will sit between — beforeId is the one directly ABOVE it, afterId the one directly BELOW; name either or both. A request naming a position and a neighbour is refused. Omitting everything puts it at the bottom — the opposite of a new ticket, which lands at the top. There is no index to compute — you name neighbours you can see and the server works out the order, so two clients moving tickets at the same time converge on one order instead of overwriting each other. A neighbour that has been deleted, or now sits in another column, is not used; if you named both and the one below now sits above the one above, the one above is kept; if neither can be used, the ticket goes to the bottom. A move never fails because your view of the board was a moment old. The answer says where it landed: placement.above and placement.below are its neighbours now, and placement.ignored names each neighbour you named that was not used and why — other_column most often means you read it off another column's list. An empty ignored means every neighbour you named was used, not that nothing sits between them: compare above and below with what you named, and if they differ and the exact place matters, re-read that column in board order and move again. Reordering inside a column leaves statusChangedAt alone. Requires a read_write key.

patch/v1/projects/{projectId}/tickets/{ticketId}/move

Request

  • Base URL: https://api.competlab.com
  • URL: https://api.competlab.com/v1/projects/{projectId}/tickets/{ticketId}/move
  • Auth: API key in header CL-API-Key

Path parameters

ticketIdstring required
Example:507f1f77bcf86cd799439011

Ticket ID

projectIdstring required
Example:507f1f77bcf86cd799439011

Project ID

Request body

status'triage' | 'todo' | 'in_progress' | 'done' | 'dismissed' required

The column the ticket sits in. triage — nobody has decided yet. todo — decided, not started. in_progress — being worked on. done — finished. dismissed — the team decided not to do it. The set is fixed and a project cannot add to it. Change it with the move endpoint, never with an update.

beforeIdstring

The ticket that will sit directly ABOVE this one. Name either neighbour or both. Omitting both puts the ticket at the BOTTOM of the destination column — which is its first card when that column is empty.

afterIdstring

The ticket that will sit directly BELOW this one. To put a ticket at the TOP of a column, send the ticket currently first there as afterId, and no beforeId.

position'top' | 'bottom'

The top or the bottom of the destination column, without reading the column first. Name a position OR neighbours: a request carrying both is refused. Omitting everything puts the ticket at the bottom.

Example request

{
  "beforeId": "507f1f77bcf86cd799439012",
  "afterId": "507f1f77bcf86cd799439013",
  "position": "top"
}

Response

Example response

{
  "item": {
    "id": "507f1f77bcf86cd799439011",
    "number": 14,
    "author": {
      "userId": "507f1f77bcf86cd799439011",
      "fullName": "Dana Ellis"
    },
    "briefing": {
      "runId": "6a3950c06bda450a1372048e",
      "estimatedMinutes": 90,
      "extendsTicketId": "507f1f77bcf86cd799439012"
    },
    "title": "Get onto the 2026 buyer guide",
    "description": "The guide names three of our competitors and not us.",
    "labels": [
      {
        "id": "3f2a9c6e-1b77-4c1e-9a54-5c7b2f0a91d2",
        "name": "Pricing page",
        "color": "#3b82f6"
      }
    ],
    "statusChangedAt": "2026-09-15T10:00:00.000Z",
    "assignee": {
      "userId": "507f1f77bcf86cd799439011",
      "fullName": "Dana Ellis"
    },
    "dueDate": "2026-10-01",
    "impact": 3,
    "commentCount": 2,
    "deletable": true,
    "createdAt": "2026-09-15T10:00:00.000Z",
    "updatedAt": "2026-09-16T08:30:00.000Z",
    "lastActivityAt": "2026-09-17T11:02:00.000Z"
  },
  "placement": {
    "above": {
      "id": "507f1f77bcf86cd799439012",
      "number": 12,
      "title": "Publish the integrations page"
    },
    "below": {
      "id": "507f1f77bcf86cd799439012",
      "number": 12,
      "title": "Publish the integrations page"
    },
    "ignored": [
      {
        "id": "507f1f77bcf86cd799439014"
      }
    ]
  }
}

Changes

    • info

      removed the non-success response with the status

    • breaking

      the response's property type changed from object to no type for status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • breaking

      removed the required property / from the response with the status

    • warning

      added the new nothing_to_return enum value to the / response property for the response status

    • warning

      added the new paging_requires_compact_view enum value to the / response property for the response status

    • warning

      added the new paging_requires_summary enum value to the / response property for the response status

    • info

      added the new optional request property

    • info

      added to the response property allOf list for the response status

    • info

      added the required property to the response with the status