API and MCP

Connect Kanbanana to your automations or AI assistants.

Authentication

API base URL: https://kanbanana.app (all REST endpoints use the prefix https://kanbanana.app/api/public/v1).

The REST API requires an API key in the Authorization: Bearer <key> header. Create keys in account settings (Pro or Team plan required).

curl -H "Authorization: Bearer fb_xxxxxxxxxxxxxxxxxxxx" \
  https://kanbanana.app/api/public/v1/boards

Machine-readable specifications

The REST specification comes from the same operation definitions used by this page. MCP tool schemas come from the live server manifest, so names, types and null handling match the /mcp endpoint. Import them into Postman, Swagger UI, a client generator or an AI assistant.

curl https://kanbanana.app/api/public/v1/openapi | jq .paths

REST API endpoints

GET/api/public/v1/boardsscope: read

Returns non-archived boards accessible to the API key owner.

No parameters.

Example response

{
  "boards": [
    {
      "id": "uuid",
      "name": "Roadmap",
      "description": null,
      "accent": "cyan",
      "icon": "rocket",
      "template": "kanban",
      "created_at": "2026-08-01T09:00:00Z",
      "updated_at": "2026-08-20T12:30:00Z"
    }
  ]
}
GET/api/public/v1/boards/{boardId}scope: read

Returns a board with its columns, cards, labels and card-label associations.

ParameterLocationTypeRequiredDescription
boardIdpathuuidyesBoard identifier.

Example response

{
  "board": { "id": "uuid", "name": "Roadmap" },
  "columns": [{ "id": "uuid", "name": "To do", "position": 1000, "wip_limit": null, "is_done_column": false }],
  "cards": [{ "id": "uuid", "column_id": "uuid", "title": "Task", "priority": "medium", "due_at": null }],
  "labels": [{ "id": "uuid", "name": "Bug", "color": "red" }],
  "cardLabels": [{ "card_id": "uuid", "label_id": "uuid" }]
}
POST/api/public/v1/boards/{boardId}/cardsscope: write

Adds a card to the end of the specified column on this board.

ParameterLocationTypeRequiredDescription
boardIdpathuuidyesBoard identifier.
titlebodystringyesCard title (1–200 characters).
columnIdbodyuuidyesTarget column; it must belong to this board.
descriptionbodystringnoCard description (maximum 5,000 characters).
prioritybodynone | low | medium | high | urgentnoCard priority.
dueAtbodydate-time | nullnoDue date in ISO 8601 format (UTC).
estimatePomodorosbodyintegernoEstimated number of Pomodoro sessions (>= 0).

Example response

{ "card": { "id": "uuid", "title": "New card", "column_id": "uuid", "position": 3000 } }
PATCH/api/public/v1/cards/{cardId}scope: write

Updates selected card fields. Provide at least one field in the request body.

ParameterLocationTypeRequiredDescription
cardIdpathuuidyesCard identifier.
titlebodystringnoNew title (1–200 characters).
columnIdbodyuuidnoMove the card to another column.
descriptionbodystring | nullnoCard description; null clears the field.
prioritybodynone | low | medium | high | urgentnoCard priority.
dueAtbodydate-time | nullnoDue date in ISO 8601 format; null removes it.
estimatePomodorosbodyinteger | nullnoEstimated number of Pomodoro sessions.
completedAtbodydate-time | nullnoCompletion date in ISO 8601 format; null marks the card as incomplete.

Example response

{ "card": { "id": "uuid", "title": "Updated title", "priority": "high" } }
DELETE/api/public/v1/cards/{cardId}scope: write

Permanently deletes a card.

ParameterLocationTypeRequiredDescription
cardIdpathuuidyesCard identifier.

Example response

{ "deleted": true }

MCP server

Kanbanana provides an MCP server that lets AI assistants (such as Claude, ChatGPT and Cursor) read boards and manage cards through OAuth. MCP endpoint: https://kanbanana.app/mcp (server kanbanana, version 0.2.1).

How to connect: in a web app (Claude or ChatGPT), add a custom connector using the URL above. Authentication uses OAuth 2.1 with dynamic client registration, so you do not need a client ID or API key. After signing in, grant consent. Tools then act on your behalf with the same permissions as your account in Kanbanana.

In clients with a configuration file (Cursor or Claude Desktop), use the same URL:

{
  "mcpServers": {
    "kanbanana": {
      "url": "https://kanbanana.app/mcp"
    }
  }
}

The tool descriptions and schemas below come directly from the live MCP server definitions. Pass parameters in the arguments field of a tools/call request; MCP does not use an HTTP request body.

list_boardsread-only

List all Kanban boards the user has access to.

No arguments.

get_boardread-only

Get a single Kanban board with its columns, cards, and labels.

ArgumentTypeRequiredConstraintsDescription
boardIdstring (uuid)yes—The board ID (UUID).
create_cardwrite

Create a new card on a Kanban board column.

ArgumentTypeRequiredConstraintsDescription
boardIdstring (uuid)yes—The board ID (UUID).
columnIdstring (uuid)yes—The column ID (UUID) to place the card in.
titlestringyes1–200 znakówCard title.
descriptionstring | nullno0–5000 znakówOptional card description (null clears it).
prioritynone | low | medium | high | urgentno—Optional priority.
dueAtstring (date-time) | nullno—Optional ISO 8601 due date/time (null for none).
estimatePomodorosinteger | nullnozakres 0–100Estimated number of Pomodoro sessions.
update_cardwrite

Update a card's title, description, priority, due date, or column.

ArgumentTypeRequiredConstraintsDescription
cardIdstring (uuid)yes—The card ID (UUID).
titlestringno1–200 znakówNew card title.
columnIdstring (uuid)no—New column ID.
descriptionstring | nullno0–5000 znakówNew description; null clears it.
prioritynone | low | medium | high | urgentno—New priority.
dueAtstring (date-time) | nullno—New ISO 8601 due date/time; null removes the due date.
estimatePomodorosinteger | nullnozakres 0–100Estimated number of Pomodoro sessions; null clears it.
completedAtstring (date-time) | nullno—Completion timestamp (ISO 8601); null marks the card as not completed.
delete_cardwritedestructive

Delete a card by ID.

ArgumentTypeRequiredConstraintsDescription
cardIdstring (uuid)yes—The card ID (UUID) to delete.

Fields in MCP responses

Results are returned in structuredContent.result. list_boards returns boards[] with fields id, name, description, accent, icon, template, created_at, updated_at. get_board returns board (without created_at), columns (id, name, color, position, wip_limit, is_done_column), cards, labels and cardLabels.

Card fieldMeaning
id / column_idIDs of the card and the column containing it.
title / descriptionCard title and description (description may be null).
prioritynone | low | medium | high | urgent.
due_atDue date in ISO 8601 (UTC), or null.
all_daytrue means an all-day deadline; the time in due_at is ignored.
assignee_idUser assigned to the card (UUID), or null. Set in the application.
estimate_pomodorosEstimated Pomodoro sessions (read and write with create_card/update_card).
completed_atCompletion date, or null for an incomplete card.
positionOrder within the column (ascending).
created_byCard creator (UUID).
created_at / updated_atCreation and update timestamps.

Rate limits

  • REST API: 1,000 requests per hour per API key.
  • Write operations (POST/PATCH/DELETE): an additional 60 requests per minute per key.
  • Requests without a valid key: 60 per hour per IP address.
  • MCP endpoint /mcp: 600 requests per hour per token (or per IP when no token is provided).

Every REST response includes X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers. When the limit is exceeded, the API returns 429 with Retry-After in seconds.

Error codes and retries

REST API errors use a consistent JSON format. The retryable field tells you whether to retry the request with exponential backoff.

{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded. Try again later.",
    "retryable": true,
    "retryAfter": 42
  }
}
StatuscodeRetry?
400invalid_request / invalid_jsonNo — fix the request
401unauthorizedNo — check the API key
402usage_limit_reachedNo — check your plan and limits
403forbiddenNo — insufficient permissions or scope
404not_foundNo
429rate_limitedYes — after Retry-After
500internal_errorYes — backoff, e.g. 5s, 10s, 20s

The MCP endpoint returns transport errors in JSON-RPC format: -32029 for rate limits and -32603 for server errors. Both include retryable and retryAfter in data. Domain errors (such as an unknown ID) return as tool results with isError: true and a structured code:

{
  "isError": true,
  "structuredContent": {
    "result": {
      "error": { "code": "not_found", "message": "No board found for the given boardId.", "retryable": false }
    }
  }
}
  • not_found — unknown or inaccessible boardId, cardId or columnId (equivalent to REST 404). Do not retry.
  • unauthenticated — missing or invalid OAuth token. Reconnect the connector.
  • forbidden — insufficient board or card permissions. Do not retry.
  • invalid_request — invalid input. Do not retry.
  • internal_error — server error; retryable: true. Retry with backoff.

Example: create a card

curl -X POST \
  -H "Authorization: Bearer fb_xxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"columnId":"column-uuid","title":"New card","priority":"high"}' \
  https://kanbanana.app/api/public/v1/boards/board-uuid/cards