Krokanti Tasks API
Automate your task management workflow with personal API tokens and a simple REST API.
https://tasks.krokanti.com/api100 req/min per tokenPro 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"Spaces
/api/spacesList all spaces the authenticated user belongs to.
- →Returns an array of space objects.
/api/spacesCreate a new team space.
| Parameter | Type | Description |
|---|---|---|
namerequired | string | Space display name. |
slugrequired | string | Unique URL-friendly identifier (3-50 chars, a-z 0-9 -). |
description | string | Optional description. |
color | string | Hex color for the space icon. |
- →The authenticated user becomes the space owner.
- →A default General project is created automatically.
Projects
/api/projectsList all projects in a space.
| Parameter | Type | Description |
|---|---|---|
spaceIdrequired | string (UUID) | The space ID. |
/api/projectsCreate a new project.
| Parameter | Type | Description |
|---|---|---|
spaceIdrequired | string (UUID) | The space to create the project in. |
namerequired | string | Project display name. |
slugrequired | string | URL-friendly identifier, unique within the space. |
description | string | Optional description. |
defaultView | kanban | list | calendar | gantt | Default view mode. |
color | string | Hex color. |
- →Requires Owner, Admin, or Member role.
- →Default statuses are created automatically.
/api/projects/:idUpdate project settings.
| Parameter | Type | Description |
|---|---|---|
idrequired | string (UUID) | Project ID. |
name | string | New display name. |
slug | string | New slug (must be unique within space). |
description | string | null | Project description. |
defaultView | kanban | list | calendar | gantt | Default view. |
- →Requires Owner or Admin role.
/api/projects/:idArchive a project. Requires Owner or Admin role.
| Parameter | Type | Description |
|---|---|---|
idrequired | string (UUID) | Project ID. |
Tasks
/api/tasksList tasks in a project.
| Parameter | Type | Description |
|---|---|---|
projectIdrequired | string (UUID) | The project ID. |
archived | boolean | true to list archived tasks. |
updatedSince | string (ISO 8601) | Only tasks changed at or after this timestamp, ordered by updatedAt. Use this for incremental syncs instead of re-reading the board. |
includeArchived | boolean | With updatedSince: include archived tasks (so you can see what left the board). |
includeSubtasks | boolean | With updatedSince: include subtasks. |
/api/tasksCreate a new task.
| Parameter | Type | Description |
|---|---|---|
projectIdrequired | string (UUID) | Project to create the task in. |
titlerequired | string | Task title. |
statusId | string (UUID) | null | Status column for the task. |
priority | none | low | medium | high | urgent | Task priority. |
dueDate | string (ISO 8601) | Due date. |
parentTaskId | string (UUID) | null | Parent task for subtasks. |
- →Requires at least Member role.
- →Position is assigned automatically.
/api/tasks/:idUpdate a task.
| Parameter | Type | Description |
|---|---|---|
idrequired | string (UUID) | Task ID. |
title | string | New title. |
statusId | string (UUID) | null | Move to a different status column. |
priority | none | low | medium | high | urgent | Priority. |
dueDate | string (ISO 8601) | null | Due date. |
completedAt | string (ISO 8601) | null | Mark done (ISO date) or reopen (null). |
isArchived | boolean | Archive or restore the task. |
estimatedHours | number | null | Time estimate in hours. |
- →Requires at least Member role.
- →Setting completedAt marks the task done.
/api/tasks/:idPermanently delete a task.
| Parameter | Type | Description |
|---|---|---|
idrequired | string (UUID) | Task ID. |
/api/tasks/:id/assigneesAssign a space member to the task. The assignee is notified (in-app + email) exactly as if a human had assigned them.
| Parameter | Type | Description |
|---|---|---|
userIdrequired | string (UUID) | Member to assign. Get it from GET /api/spaces/:id/members. |
/api/tasks/:id/assignees/:userIdRemove an assignee. Idempotent — removing someone who isn't assigned succeeds.
| Parameter | Type | Description |
|---|---|---|
userIdrequired | string (UUID) | Assignee to remove. |
/api/tasks/:id/labelsAttach a label to the task. Labels are project-scoped.
| Parameter | Type | Description |
|---|---|---|
labelIdrequired | string (UUID) | Label from GET /api/projects/:id/labels. |
/api/tasks/:id/labels/:labelIdDetach a label from the task.
/api/tasks/:id/commentsList the task's comments, newest last. Supports limit and offset.
/api/tasks/:id/commentsPost a comment. Assignees and @-mentioned members are notified.
| Parameter | Type | Description |
|---|---|---|
contentrequired | string | Comment body (HTML; plain text is wrapped). |
/api/tasks/:id/activityTask history — status changes, assignments, edits. Retention depends on the space plan (7 days Free, 90 days Pro, unlimited Team+).
/api/spaces/:id/membersList space members with userId, name, email and role — the userId the assignee endpoints expect.
Webhooks
Subscreve um endpoint HTTPS aos eventos de tarefas e o Krokanti Tasks envia-te as alterações no momento em que acontecem. É a forma suportada de manter um sistema externo (GitHub Issues, Linear, um bot de Slack, a tua própria base de dados) sincronizado.
Eventos
| Evento | Disparado quando |
|---|---|
task.created | Uma tarefa é criada. |
task.updated | Qualquer campo muda. Reordenar dentro da coluna não dispara evento. |
task.moved | A tarefa muda de coluna de estado, ou passa para outro projeto. |
task.assigned | Alguém é atribuído. data.assignee contém o utilizador. |
task.unassigned | Uma atribuição é removida. data.assignee contém o utilizador. |
task.completed | A tarefa é marcada como concluída. |
task.reopened | Uma tarefa concluída é reaberta. |
task.archived | A tarefa é arquivada (escondida do quadro, ainda recuperável). |
task.unarchived | Uma tarefa arquivada é restaurada. |
task.deleted | A tarefa é eliminada permanentemente. O payload leva o retrato anterior à eliminação. |
task.commented | É publicado um comentário. data.comment contém-no. |
Um envio por alteração: cada webhook recebe o evento mais específico a que subscreveu. Um webhook que só conhece task.updated continua a receber um envio quando uma tarefa é movida, atribuída ou arquivada — as integrações antigas continuam a funcionar.
Payload
Os envios são POST com corpo JSON. O objeto task vem sempre completo (estado, atribuídos, etiquetas, datas), pelo que raramente precisas de uma leitura adicional.
{
"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..." } }
}
}Cabeçalhos
Todos os envios de plataforma personalizada trazem estes cabeçalhos. Usa X-Krokanti-Delivery para desduplicar repetições.
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/1Verificar a assinatura
A assinatura é um HMAC-SHA256 do corpo bruto exato do pedido, com o segredo do webhook como chave. Compara-a em tempo constante e sobre o corpo bruto — se fizeres parse e voltares a serializar não vai coincidir.
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
}Semântica de entrega
Cada envio expira aos 4 s e é repetido uma vez em caso de timeout, erro de rede, 5xx ou 429. Um 4xx é tratado como rejeição permanente e não é repetido. Ao fim de 10 falhas seguidas o webhook é desativado automaticamente — reativa-o nas definições do espaço.
Gerir webhooks
/api/spaces/:id/webhooksLista os webhooks de um espaço, com o segredo, eventos subscritos e estado do último envio. Só owner/admin.
/api/spaces/:id/webhooksCria um webhook. Devolve o segredo de assinatura. Requer plano Pro ou Team (5 webhooks no Pro, 10 no Team+).
| Parameter | Type | Description |
|---|---|---|
namerequired | string | Label for this integration. |
urlrequired | string (HTTPS) | Endpoint that receives the POSTs. |
eventsrequired | string[] | Events to subscribe to (see the table above). |
platform | custom | slack | discord | custom (default) sends the JSON payload; slack/discord send formatted messages and require Team+. |
/api/spaces/:id/webhooks/:webhookIdAtualiza o nome, URL ou eventos de um webhook, ou ativa/desativa-o.
| Parameter | Type | Description |
|---|---|---|
name | string | New label. |
url | string (HTTPS) | New endpoint. |
events | string[] | Replace the subscribed events. |
isActive | boolean | Enable or disable. Enabling resets the failure counter. |
/api/spaces/:id/webhooks/:webhookIdElimina uma subscrição de webhook.
/api/spaces/:id/webhooks/:webhookId/testEnvia um payload de teste para o endpoint — mesmos cabeçalhos e assinatura de um real. Usa-o para validar o teu código de verificação.
Error codes
Error responses include an error field and optionally a code field.
| Status | Meaning | Common cause |
|---|---|---|
400 | Bad Request | Missing or invalid fields. |
401 | Unauthorized | Missing or invalid API token. |
402 | Payment Required | API access requires Pro or Team. |
403 | Forbidden | Insufficient role. |
404 | Not Found | Resource does not exist. |
409 | Conflict | Slug already taken. |
429 | Too Many Requests | Exceeded 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
| Tool | Description | Key inputs |
|---|---|---|
list_spaces | List all spaces the user belongs to | — |
list_projects | List projects in a space | spaceId |
list_statuses | List status columns in a project | projectId |
list_tasks | List tasks; updatedSince for incremental syncs | projectId, updatedSince?, includeArchived?, includeSubtasks?, limit? |
get_task | Full detail: assignees, labels, subtasks, comments | taskId |
create_task | Create a new task | projectId, title, description?, statusId?, priority?, dueDate?, parentTaskId? |
update_task | Update title, description, status, priority, due date, hours | taskId + fields to change |
complete_task | Mark done or reopen a task | taskId, reopen? |
archive_task | Archive a task or restore it (reversible) | taskId, archived? |
delete_task | Delete a task permanently (irreversible) | taskId |
add_comment | Add a comment to a task | taskId, content |
list_members | Space members with their userId and role | spaceId |
assign_task | Assign a space member to a task | taskId, userId |
unassign_task | Remove an assignee from a task | taskId, userId |
list_labels | List a project's labels | projectId |
set_task_labels | Attach and/or detach labels on a task | taskId, add?, remove? |
list_webhooks | List a space's webhook subscriptions | spaceId |
create_webhook | Subscribe an endpoint to task events | spaceId, name, url, events |
delete_webhook | Remove a webhook subscription | spaceId, 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
| Prompt | Description | Inputs |
|---|---|---|
plan_sprint | Review a project and suggest a prioritized sprint plan | projectId, goal? |
daily_standup | Generate a done/in-progress/next/blockers report | projectId, userName? |
Prompts guide the AI to use multiple tools together for common workflows.