Krokanti Tasks
REST API

Krokanti Tasks API

Automate your task management workflow with personal API tokens and a simple REST API.

Base URL:https://tasks.krokanti.com/api
Rate limit:100 req/min per token

Pro or Team plan required

API access is available on Pro and Team plans. Generate tokens in Settings → API Tokens.

Upgrade your plan →

Authentication

All API requests must include an Authorization header with a personal API token. Generate tokens in Settings → API Tokens. Tokens start with kt_ and are shown once on creation.

curl https://tasks.krokanti.com/api/spaces 
  -H "Authorization: Bearer kt_your_token_here" 
  -H "Content-Type: application/json"
Security note: Tokens cannot manage other tokens. Store them securely.

Spaces

GET/api/spaces

List all spaces the authenticated user belongs to.

  • Returns an array of space objects.
POST/api/spaces

Create a new team space.

ParameterTypeDescription
namerequiredstringSpace display name.
slugrequiredstringUnique URL-friendly identifier (3-50 chars, a-z 0-9 -).
descriptionstringOptional description.
colorstringHex color for the space icon.
  • The authenticated user becomes the space owner.
  • A default General project is created automatically.

Projects

GET/api/projects

List all projects in a space.

ParameterTypeDescription
spaceIdrequiredstring (UUID)The space ID.
POST/api/projects

Create a new project.

ParameterTypeDescription
spaceIdrequiredstring (UUID)The space to create the project in.
namerequiredstringProject display name.
slugrequiredstringURL-friendly identifier, unique within the space.
descriptionstringOptional description.
defaultViewkanban | list | calendar | ganttDefault view mode.
colorstringHex color.
  • Requires Owner, Admin, or Member role.
  • Default statuses are created automatically.
PATCH/api/projects/:id

Update project settings.

ParameterTypeDescription
idrequiredstring (UUID)Project ID.
namestringNew display name.
slugstringNew slug (must be unique within space).
descriptionstring | nullProject description.
defaultViewkanban | list | calendar | ganttDefault view.
  • Requires Owner or Admin role.
DELETE/api/projects/:id

Archive a project. Requires Owner or Admin role.

ParameterTypeDescription
idrequiredstring (UUID)Project ID.

Tasks

GET/api/tasks

List tasks in a project.

ParameterTypeDescription
projectIdrequiredstring (UUID)The project ID.
archivedbooleantrue to list archived tasks.
updatedSincestring (ISO 8601)Only tasks changed at or after this timestamp, ordered by updatedAt. Use this for incremental syncs instead of re-reading the board.
includeArchivedbooleanWith updatedSince: include archived tasks (so you can see what left the board).
includeSubtasksbooleanWith updatedSince: include subtasks.
POST/api/tasks

Create a new task.

ParameterTypeDescription
projectIdrequiredstring (UUID)Project to create the task in.
titlerequiredstringTask title.
statusIdstring (UUID) | nullStatus column for the task.
prioritynone | low | medium | high | urgentTask priority.
dueDatestring (ISO 8601)Due date.
parentTaskIdstring (UUID) | nullParent task for subtasks.
  • Requires at least Member role.
  • Position is assigned automatically.
PATCH/api/tasks/:id

Update a task.

ParameterTypeDescription
idrequiredstring (UUID)Task ID.
titlestringNew title.
statusIdstring (UUID) | nullMove to a different status column.
prioritynone | low | medium | high | urgentPriority.
dueDatestring (ISO 8601) | nullDue date.
completedAtstring (ISO 8601) | nullMark done (ISO date) or reopen (null).
isArchivedbooleanArchive or restore the task.
estimatedHoursnumber | nullTime estimate in hours.
  • Requires at least Member role.
  • Setting completedAt marks the task done.
DELETE/api/tasks/:id

Permanently delete a task.

ParameterTypeDescription
idrequiredstring (UUID)Task ID.
POST/api/tasks/:id/assignees

Assign a space member to the task. The assignee is notified (in-app + email) exactly as if a human had assigned them.

ParameterTypeDescription
userIdrequiredstring (UUID)Member to assign. Get it from GET /api/spaces/:id/members.
DELETE/api/tasks/:id/assignees/:userId

Remove an assignee. Idempotent — removing someone who isn't assigned succeeds.

ParameterTypeDescription
userIdrequiredstring (UUID)Assignee to remove.
POST/api/tasks/:id/labels

Attach a label to the task. Labels are project-scoped.

ParameterTypeDescription
labelIdrequiredstring (UUID)Label from GET /api/projects/:id/labels.
DELETE/api/tasks/:id/labels/:labelId

Detach a label from the task.

GET/api/tasks/:id/comments

List the task's comments, newest last. Supports limit and offset.

POST/api/tasks/:id/comments

Post a comment. Assignees and @-mentioned members are notified.

ParameterTypeDescription
contentrequiredstringComment body (HTML; plain text is wrapped).
GET/api/tasks/:id/activity

Task history — status changes, assignments, edits. Retention depends on the space plan (7 days Free, 90 days Pro, unlimited Team+).

GET/api/spaces/:id/members

List space members with userId, name, email and role — the userId the assignee endpoints expect.

Webhooks

Abonniere einen HTTPS-Endpunkt für Aufgaben-Events und Krokanti Tasks schickt dir Änderungen in dem Moment, in dem sie passieren. So hältst du ein externes System (GitHub Issues, Linear, einen Slack-Bot, deine eigene Datenbank) synchron.

Nicht per Timer pollen. Ein Cron, der jede Minute das ganze Board neu liest, hält die serverlose Datenbank wach und hinkt trotzdem hinterher. Wenn du pollen musst, nutze GET /api/tasks?updatedSince=<ISO 8601> und lies nur das Geänderte.

Events

EventWird ausgelöst, wenn
task.createdEine Aufgabe wird erstellt.
task.updatedEin Feld ändert sich. Reines Umsortieren löst kein Event aus.
task.movedDie Aufgabe wechselt die Statusspalte oder das Projekt.
task.assignedJemand wird zugewiesen. data.assignee enthält den Nutzer.
task.unassignedEine Zuweisung wird entfernt. data.assignee enthält den Nutzer.
task.completedDie Aufgabe wird als erledigt markiert.
task.reopenedEine erledigte Aufgabe wird wieder geöffnet.
task.archivedDie Aufgabe wird archiviert (vom Board ausgeblendet, weiterhin wiederherstellbar).
task.unarchivedEine archivierte Aufgabe wird wiederhergestellt.
task.deletedDie Aufgabe wird endgültig gelöscht. Das Payload enthält den Stand vor dem Löschen.
task.commentedEin Kommentar wird gepostet. data.comment enthält ihn.

Eine Zustellung pro Änderung: Jeder Webhook erhält das spezifischste Event, das er abonniert hat. Ein Webhook, der nur task.updated kennt, bekommt weiterhin eine Zustellung, wenn eine Aufgabe verschoben, zugewiesen oder archiviert wird — ältere Integrationen laufen unverändert weiter.

Payload

Zustellungen sind POSTs mit JSON-Body. Das task-Objekt ist immer vollständig (Status, Zuweisungen, Labels, Daten) — ein Nachladen ist selten nötig.

{
  "id": "b1e1c0de-...",                  // delivery id — de-duplicate on this
  "event": "task.moved",
  "timestamp": "2026-07-27T09:14:22.104Z",
  "data": {
    "task": {
      "id": "6f0c...", "title": "Ship the webhook docs",
      "description": "<p>...</p>",
      "priority": "high",
      "statusId": "2a91...",
      "status": { "id": "2a91...", "name": "In progress", "type": "in_progress" },
      "dueDate": "2026-07-30T00:00:00.000Z",
      "startDate": null,
      "completedAt": null,
      "isArchived": false,
      "parentTaskId": null,
      "createdAt": "2026-07-20T08:00:00.000Z",
      "updatedAt": "2026-07-27T09:14:22.041Z",
      "assignees": [{ "id": "9c2f...", "name": "Edgar" }],
      "labels": [{ "id": "77aa...", "name": "docs", "color": "#c07f3a" }],
      "url": "https://tasks.krokanti.com/en/app/my-space/my-project?taskId=6f0c..."
    },
    "project": { "id": "4d5e...", "name": "My project", "slug": "my-project" },
    "space":   { "id": "1a2b...", "slug": "my-space" },
    "actor":   { "id": "9c2f...", "name": "Edgar" },
    "comment": null,
    "assignee": null,
    "changes": { "statusId": { "from": "1f00...", "to": "2a91..." } }
  }
}

Header

Jede Zustellung an eine eigene Plattform trägt diese Header. Nutze X-Krokanti-Delivery, um Wiederholungen zu deduplizieren.

X-Krokanti-Event:         task.moved
X-Krokanti-Delivery:      b1e1c0de-...          # unique per delivery
X-Krokanti-Timestamp:     2026-07-27T09:14:22.104Z
X-Krokanti-Signature:     3f8a...               # HMAC-SHA256 hex of the raw body
X-Krokanti-Signature-256: sha256=3f8a...        # same value, GitHub-style prefix
User-Agent:               Krokanti-Tasks-Webhook/1

Signatur prüfen

Die Signatur ist ein HMAC-SHA256 über den exakten Roh-Body, mit dem Webhook-Secret als Schlüssel. Vergleiche sie in konstanter Zeit und über den Roh-Body — erst parsen und neu serialisieren passt nicht.

import crypto from "crypto";

export async function POST(req: Request) {
  const raw = await req.text();                  // raw body, before JSON.parse
  const sent = req.headers.get("x-krokanti-signature") ?? "";
  const expected = crypto
    .createHmac("sha256", process.env.KROKANTI_WEBHOOK_SECRET!)
    .update(raw)
    .digest("hex");

  const a = Buffer.from(sent), b = Buffer.from(expected);
  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
    return new Response("invalid signature", { status: 401 });
  }

  const payload = JSON.parse(raw);
  // ... handle payload.event, de-duplicate on payload.id
  return new Response("ok");                     // respond 2xx fast; queue slow work
}

Zustellverhalten

Eine Zustellung läuft nach 4 s ab und wird bei Timeout, Netzwerkfehler, 5xx oder 429 einmal wiederholt. Ein 4xx gilt als endgültige Ablehnung und wird nicht wiederholt. Nach 10 Fehlern in Folge wird der Webhook automatisch deaktiviert — reaktiviere ihn in den Space-Einstellungen.

Webhooks verwalten

GET/api/spaces/:id/webhooks

Listet die Webhooks eines Space mit Secret, abonnierten Events und letztem Zustellstatus. Nur Owner/Admin.

POST/api/spaces/:id/webhooks

Erstellt einen Webhook. Gibt das Signatur-Secret zurück. Erfordert Pro oder Team (5 Webhooks bei Pro, 10 ab Team).

ParameterTypeDescription
namerequiredstringLabel for this integration.
urlrequiredstring (HTTPS)Endpoint that receives the POSTs.
eventsrequiredstring[]Events to subscribe to (see the table above).
platformcustom | slack | discordcustom (default) sends the JSON payload; slack/discord send formatted messages and require Team+.
PATCH/api/spaces/:id/webhooks/:webhookId

Aktualisiert Name, URL oder Events eines Webhooks oder (de)aktiviert ihn.

ParameterTypeDescription
namestringNew label.
urlstring (HTTPS)New endpoint.
eventsstring[]Replace the subscribed events.
isActivebooleanEnable or disable. Enabling resets the failure counter.
DELETE/api/spaces/:id/webhooks/:webhookId

Löscht ein Webhook-Abonnement.

POST/api/spaces/:id/webhooks/:webhookId/test

Sendet eine Test-Zustellung an den Endpunkt — gleiche Header und Signatur wie im Ernstfall. Damit prüfst du deinen Verifizierungscode.

Error codes

Error responses include an error field and optionally a code field.

StatusMeaningCommon cause
400Bad RequestMissing or invalid fields.
401UnauthorizedMissing or invalid API token.
402Payment RequiredAPI access requires Pro or Team.
403ForbiddenInsufficient role.
404Not FoundResource does not exist.
409ConflictSlug already taken.
429Too Many RequestsExceeded 100 req/min per token.
// Error response body
{ "error": "Unauthorized" }

// With machine-readable subcode
{ "error": "API access requires a Pro or Team plan", "code": "pro_required" }

Rate limits

API token requests are limited to 100 requests per minute per token.

When you exceed the limit you receive 429 Too Many Requests. The response includes a Retry-After header with seconds to wait.

HTTP/1.1 429 Too Many Requests
Retry-After: 42
Content-Type: application/json

{ "error": "Rate limit exceeded" }

Code examples

Replace kt_your_token_here with your actual token.

cURL

# List your spaces
curl "https://tasks.krokanti.com/api/spaces" 
  -H "Authorization: Bearer kt_your_token_here"

# List projects in a space
curl "https://tasks.krokanti.com/api/projects?spaceId=SPACE_ID" 
  -H "Authorization: Bearer kt_your_token_here"

# List tasks in a project
curl "https://tasks.krokanti.com/api/tasks?projectId=PROJECT_ID" 
  -H "Authorization: Bearer kt_your_token_here"

# Create a task
curl -X POST "https://tasks.krokanti.com/api/tasks" 
  -H "Authorization: Bearer kt_your_token_here" 
  -H "Content-Type: application/json" 
  -d '{ "projectId": "PROJECT_ID", "title": "My new task", "priority": "high" }'

# Complete a task
curl -X PATCH "https://tasks.krokanti.com/api/tasks/TASK_ID" 
  -H "Authorization: Bearer kt_your_token_here" 
  -H "Content-Type: application/json" 
  -d '{ "completedAt": "2026-02-22T10:00:00.000Z" }'

JavaScript / Node

const BASE = "https://tasks.krokanti.com/api";
const TOKEN = "kt_your_token_here";
const headers = {
  Authorization: `Bearer ${TOKEN}`,
  "Content-Type": "application/json",
};

// List spaces
const spaces = await fetch(`${BASE}/spaces`, { headers }).then(r => r.json());

// List projects in first space
const projects = await fetch(
  `${BASE}/projects?spaceId=${spaces[0].id}`,
  { headers }
).then(r => r.json());

// Create a task
const { task } = await fetch(`${BASE}/tasks`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    projectId: projects[0].id,
    title: "Review pull request",
    priority: "high",
    dueDate: new Date(Date.now() + 86400000).toISOString(),
  }),
}).then(r => r.json());

// Mark it done
await fetch(`${BASE}/tasks/${task.id}`, {
  method: "PATCH",
  headers,
  body: JSON.stringify({ completedAt: new Date().toISOString() }),
});

Python

import requests
from datetime import datetime, timedelta, timezone

BASE = "https://tasks.krokanti.com/api"
TOKEN = "kt_your_token_here"
HEADERS = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}

# List spaces
spaces = requests.get(f"{BASE}/spaces", headers=HEADERS).json()

# List projects
projects = requests.get(
    f"{BASE}/projects", headers=HEADERS,
    params={"spaceId": spaces[0]["id"]}
).json()

# Create a task
tomorrow = (datetime.now(timezone.utc) + timedelta(days=1)).isoformat()
resp = requests.post(f"{BASE}/tasks", headers=HEADERS, json={
    "projectId": projects[0]["id"],
    "title": "Deploy new release",
    "priority": "urgent",
    "dueDate": tomorrow,
})
task = resp.json()["task"]
print(f"Created task: {task['id']}")

# Complete the task
requests.patch(f"{BASE}/tasks/{task['id']}", headers=HEADERS, json={
    "completedAt": datetime.now(timezone.utc).isoformat()
})

MCP — AI Integration

Krokanti Tasks ships with a built-in MCP (Model Context Protocol) server. Connect Claude Code, Claude Desktop, or Cursor to your tasks and let AI create, update, and query tasks on your behalf — using the same API token.

Claude Code

Create a .mcp.json file in the root of your project (or add to an existing one):

// .mcp.json (project root)
{
  "mcpServers": {
    "krokanti-tasks": {
      "type": "http",
      "url": "https://tasks.krokanti.com/api/mcp",
      "headers": {
        "Authorization": "Bearer kt_your_token_here"
      }
    }
  }
}

Claude Code also needs the server enabled. Create .claude/settings.local.json in the same directory:

// .claude/settings.local.json
{
  "enableAllProjectMcpServers": true,
  "enabledMcpjsonServers": ["krokanti-tasks"]
}

Claude Desktop

Add to your Claude Desktop configuration file. On macOS the file is at ~/Library/Application Support/Claude/claude_desktop_config.json. On Windows: %APPDATA%Claudeclaude_desktop_config.json.

// claude_desktop_config.json
{
  "mcpServers": {
    "krokanti-tasks": {
      "command": "npx",
      "args": [
        "mcp-remote@latest",
        "https://tasks.krokanti.com/api/mcp",
        "--header",
        "Authorization: Bearer kt_your_token_here"
      ]
    }
  }
}

Cursor

Add to .cursor/mcp.json in your project root (project-level) or ~/.cursor/mcp.json for global access:

// .cursor/mcp.json  (or ~/.cursor/mcp.json for global)
{
  "mcpServers": {
    "krokanti-tasks": {
      "type": "http",
      "url": "https://tasks.krokanti.com/api/mcp",
      "headers": {
        "Authorization": "Bearer kt_your_token_here"
      }
    }
  }
}

Available tools

ToolDescriptionKey inputs
list_spacesList all spaces the user belongs to
list_projectsList projects in a spacespaceId
list_statusesList status columns in a projectprojectId
list_tasksList tasks; updatedSince for incremental syncsprojectId, updatedSince?, includeArchived?, includeSubtasks?, limit?
get_taskFull detail: assignees, labels, subtasks, commentstaskId
create_taskCreate a new taskprojectId, title, description?, statusId?, priority?, dueDate?, parentTaskId?
update_taskUpdate title, description, status, priority, due date, hourstaskId + fields to change
complete_taskMark done or reopen a tasktaskId, reopen?
archive_taskArchive a task or restore it (reversible)taskId, archived?
delete_taskDelete a task permanently (irreversible)taskId
add_commentAdd a comment to a tasktaskId, content
list_membersSpace members with their userId and rolespaceId
assign_taskAssign a space member to a tasktaskId, userId
unassign_taskRemove an assignee from a tasktaskId, userId
list_labelsList a project's labelsprojectId
set_task_labelsAttach and/or detach labels on a tasktaskId, add?, remove?
list_webhooksList a space's webhook subscriptionsspaceId
create_webhookSubscribe an endpoint to task eventsspaceId, name, url, events
delete_webhookRemove a webhook subscriptionspaceId, webhookId

All write operations (create, update, complete, add_comment, assign) require at least Member role in the space. Viewer role is read-only.

Built-in prompts

PromptDescriptionInputs
plan_sprintReview a project and suggest a prioritized sprint planprojectId, goal?
daily_standupGenerate a done/in-progress/next/blockers reportprojectId, userName?

Prompts guide the AI to use multiple tools together for common workflows.