| name | kanboard |
| version | 1.0.0 |
| description | Interact with Kanboard project management via JSON-RPC API. Use when working with Kanboard tasks, projects, boards, columns, swimlanes, comments, subtasks, and users. Trigger on: "create task", "move task", "show board", "list projects", "add comment", "kanboard", "kanban task". Supports both Application API (token) and User API (login/password).
|
| metadata | {"clawdbot":{"env":["KANBOARD_URL","KANBOARD_API_TOKEN"],"requires":["curl","jq"]}} |
Kanboard Skill
Overview
Kanboard uses JSON-RPC 2.0 over HTTP POST. All calls go to a single endpoint.
Auth modes
| Mode | User | Password |
|---|
| Application API | jsonrpc | $KANBOARD_API_TOKEN |
| User API | $KANBOARD_USER | $KANBOARD_PASS |
Application API skips permission checks and has no session. Use it for automation.
User API respects project permissions; required for "My…" procedures.
Core Helper
Always use this shell function to call the API:
kb() {
local method="$1"
local params="${2:-{}}"
local user="${KANBOARD_USER:-jsonrpc}"
local pass="${KANBOARD_PASS:-$KANBOARD_API_TOKEN}"
curl -s -X POST \
-u "$user:$pass" \
-H "Content-Type: application/json" \
-d "{\"jsonrpc\":\"2.0\",\"method\":\"$method\",\"id\":1,\"params\":$params}" \
"${KANBOARD_URL}/jsonrpc.php" | jq .
}
Check for errors in every response:
result=$(kb getMe | jq '.result')
if [ "$result" = "null" ] || [ "$result" = "false" ]; then
echo "Error: $(kb getMe | jq -r '.error.message // "unknown error"')"
fi
Projects
kb getAllProjects
kb getProjectById '{"project_id": 1}'
kb getProjectByName '{"name": "My Project"}'
kb createProject '{"name": "New Project", "description": "Optional description"}'
kb updateProject '{"id": 1, "name": "Renamed", "description": "Updated"}'
kb removeProject '{"project_id": 1}'
kb enableProject '{"project_id": 1}'
kb disableProject '{"project_id": 1}'
kb getProjectActivity '{"project_id": 1}'
Board & Columns
kb getBoard '{"project_id": 1}'
kb getColumns '{"project_id": 1}'
kb getColumn '{"column_id": 5}'
kb addColumn '{"project_id": 1, "title": "In Review", "task_limit": 3}'
kb updateColumn '{"column_id": 5, "title": "Review", "task_limit": 5}'
kb removeColumn '{"column_id": 5}'
kb changeColumnPosition '{"project_id": 1, "column_id": 5, "position": 2}'
Tasks
kb createTask '{
"title": "Fix login bug",
"project_id": 1,
"column_id": 2,
"swimlane_id": 1,
"color_id": "red",
"priority": 2,
"due_date": "2025-12-31",
"description": "Detailed description here",
"owner_id": 3,
"tags": ["bug", "urgent"]
}'
kb getTask '{"task_id": 42}'
kb getTaskByReference '{"project_id": 1, "reference": "EXT-123"}'
kb getAllTasks '{"project_id": 1, "status_id": 1}'
kb searchTasks '{"project_id": 1, "query": "assignee:me status:open"}'
kb updateTask '{
"id": 42,
"title": "Fix login bug (updated)",
"column_id": 3,
"color_id": "green",
"priority": 1,
"due_date": "2025-11-30"
}'
kb moveTaskToColumn '{
"project_id": 1,
"task_id": 42,
"column_id": 3,
"position": 1,
"swimlane_id": 1
}'
kb moveTaskToProject '{
"task_id": 42,
"project_id": 2,
"swimlane_id": 1,
"column_id": 1,
"category_id": 0
}'
kb duplicateTaskToProject '{
"task_id": 42,
"project_id": 2
}'
kb closeTask '{"task_id": 42}'
kb openTask '{"task_id": 42}'
kb removeTask '{"task_id": 42}'
kb getTaskColors
Task color IDs
yellow, blue, green, purple, red, orange, grey, brown, deep_orange, dark_grey, pink, teal, cyan, lime, light_green, amber
Subtasks
kb getAllSubtasks '{"task_id": 42}'
kb createSubtask '{
"task_id": 42,
"title": "Write unit tests",
"user_id": 3,
"time_estimated": 4
}'
kb updateSubtask '{
"id": 10,
"task_id": 42,
"status": 1,
"time_spent": 2
}'
kb removeSubtask '{"subtask_id": 10}'
Comments
kb getAllComments '{"task_id": 42}'
kb createComment '{
"task_id": 42,
"user_id": 1,
"content": "This is a **markdown** comment."
}'
kb updateComment '{"id": 7, "content": "Updated comment text."}'
kb removeComment '{"comment_id": 7}'
Swimlanes
kb getSwimlanes '{"project_id": 1}'
kb getActiveSwimlanes '{"project_id": 1}'
kb addSwimlane '{"project_id": 1, "name": "Team Alpha"}'
kb updateSwimlane '{"swimlane_id": 3, "name": "Team Beta"}'
kb removeSwimlane '{"project_id": 1, "swimlane_id": 3}'
kb changeSwimlanePosition '{"project_id": 1, "swimlane_id": 3, "position": 1}'
Categories
kb getAllCategories '{"project_id": 1}'
kb createCategory '{"project_id": 1, "name": "Backend"}'
kb updateCategory '{"id": 5, "name": "Backend & API"}'
kb removeCategory '{"category_id": 5}'
Users
kb getAllUsers
kb getUserById '{"user_id": 3}'
kb getUserByName '{"username": "alice"}'
kb createUser '{
"username": "bob",
"password": "S3cur3P@ss",
"name": "Bob Smith",
"email": "bob@example.com",
"role": "app-user"
}'
kb updateUser '{"id": 3, "name": "Bob Jones", "email": "bob.jones@example.com"}'
kb disableUser '{"user_id": 3}'
kb enableUser '{"user_id": 3}'
kb removeUser '{"user_id": 3}'
kb getMe
kb getMyProjects
kb getMyDashboard
kb getMyActivityStream
kb getMyCalendar
kb getMyNotifications
Project Permissions
kb getProjectUsers '{"project_id": 1}'
kb addProjectUser '{
"project_id": 1,
"user_id": 3,
"role": "project-member"
}'
kb changeProjectUserRole '{"project_id": 1, "user_id": 3, "role": "project-manager"}'
kb removeProjectUser '{"project_id": 1, "user_id": 3}'
kb addProjectGroup '{"project_id": 1, "group_id": 2, "role": "project-member"}'
kb removeProjectGroup '{"project_id": 1, "group_id": 2}'
Tags
kb getTagsByProject '{"project_id": 1}'
kb createTag '{"project_id": 1, "tag": "urgent"}'
kb updateTag '{"id": 4, "tag": "critical"}'
kb removeTag '{"tag_id": 4}'
kb getTaskTags '{"task_id": 42}'
kb setTaskTags '{"project_id": 1, "task_id": 42, "tags": ["bug", "urgent"]}'
Task Links (Internal)
kb getAllLinks
kb getAllTaskLinks '{"task_id": 42}'
kb createTaskLink '{
"task_id": 42,
"opposite_task_id": 55,
"link_id": 1
}'
kb removeTaskLink '{"task_link_id": 8}'
Application
kb getVersion
kb getTimezone
kb getDefaultLanguage
kb now
kb getDefaultTaskColors
Common Workflows
Create project with full setup
project_id=$(kb createProject '{"name":"Sprint 1"}' | jq '.result')
kb addColumn "{\"project_id\": $project_id, \"title\": \"Backlog\"}"
kb addColumn "{\"project_id\": $project_id, \"title\": \"In Progress\", \"task_limit\": 3}"
kb addColumn "{\"project_id\": $project_id, \"title\": \"Review\"}"
kb addColumn "{\"project_id\": $project_id, \"title\": \"Done\"}"
kb addSwimlane "{\"project_id\": $project_id, \"name\": \"Team Alpha\"}"
kb getBoard "{\"project_id\": $project_id}"
Move task through workflow
task_id=42
project_id=1
columns=$(kb getColumns "{\"project_id\": $project_id}" | jq '.result')
in_progress_col=$(echo $columns | jq '[.[] | select(.title=="In Progress")][0].id')
kb moveTaskToColumn "{
\"project_id\": $project_id,
\"task_id\": $task_id,
\"column_id\": $in_progress_col,
\"position\": 1
}"
Create task with subtasks
task_id=$(kb createTask '{
"title": "Implement feature X",
"project_id": 1,
"priority": 2
}' | jq '.result')
kb createSubtask "{\"task_id\": $task_id, \"title\": \"Write spec\"}"
kb createSubtask "{\"task_id\": $task_id, \"title\": \"Implement\"}"
kb createSubtask "{\"task_id\": $task_id, \"title\": \"Write tests\"}"
kb createSubtask "{\"task_id\": $task_id, \"title\": \"Code review\"}"
Bulk close completed tasks
project_id=1
kb getAllTasks "{\"project_id\": $project_id, \"status_id\": 1}" \
| jq -r '.result[] | select(.tags[]? == "done") | .id' \
| while read task_id; do
kb closeTask "{\"task_id\": $task_id}"
echo "Closed task $task_id"
done
Error Handling
kb_safe() {
local result
result=$(kb "$@")
local error=$(echo "$result" | jq -r '.error // empty')
if [ -n "$error" ]; then
echo "❌ API Error: $(echo "$result" | jq -r '.error.message')" >&2
return 1
fi
echo "$result" | jq '.result'
}
kb_safe getAllProjects
kb_safe getTask '{"task_id": 99999}'
Setup & Configuration
Add to your OpenClaw environment:
export KANBOARD_URL="https://kanboard.example.com"
export KANBOARD_API_TOKEN="your_token_from_settings_page"
export KANBOARD_USER="your_username"
export KANBOARD_PASS="your_password_or_personal_token"
Getting your API token:
- Log in to Kanboard as admin
- Go to Settings → API
- Copy the token shown there
Personal API token (User API):
- Click your profile avatar → My Profile
- Click "Generate a new API token" in the API section
- Use as
KANBOARD_PASS with your username as KANBOARD_USER
Notes
- All dates use
YYYY-MM-DD format or Unix timestamps
- Task
priority: 0=low, 1=normal, 2=high, 3=urgent
- Kanboard supports batch requests — multiple JSON-RPC calls in one HTTP request (useful for bulk ops)
status_id for tasks: 1=open, 2=closed
- API endpoint is always
<KANBOARD_URL>/jsonrpc.php