How to Perform Bulk Task Operations and Imports in Kaneo
Kaneo's bulk-task API lets you apply status changes, assignments, labels, and deletions to multiple tasks at once via a single PATCH request to /api/task/bulk.
Kaneo is an open-source project management platform that treats bulk actions as first-class citizens. Whether you're cleaning up completed tasks, reassigning an entire sprint, or importing work from an external system, the bulk operations architecture in Kaneo makes mass updates efficient and permission-aware. This guide walks through the API design, frontend integration, and practical patterns for bulk task operations and imports.
Understanding Kaneo's Bulk Task API
The core bulk functionality lives in the Bulk-Update-Tasks controller at apps/api/src/task/controllers/bulk-update-tasks.ts. This controller handles the PATCH /api/task/bulk endpoint and validates every request against workspace membership before executing database operations.
Request Payload Structure
Every bulk request requires three fields:
| Field | Type | Description |
|---|---|---|
taskIds |
string[] |
Array of task UUIDs to modify |
operation |
string |
The operation to perform (see supported operations below) |
value |
string | null | undefined |
Operation-specific value (omitted for delete) |
The controller enforces a critical constraint: all tasks must belong to the same workspace, and the requesting user must have access to that workspace. This prevents cross-tenant data leaks.
Supported Bulk Operations
Kaneo supports seven distinct bulk operations as implemented in the controller:
| Operation | Required value |
Effect on Tasks |
|---|---|---|
updateStatus |
Column slug ("planned", "in-progress", "done", etc.) |
Moves tasks to a new board column |
updatePriority |
Priority string ("low", "medium", "high") |
Updates priority field |
updateAssignee |
User ID string or omitted | Reassigns to user or unassigns |
delete |
None | Permanently deletes selected tasks |
addLabel |
Label ID | Attaches label to each task |
removeLabel |
Label ID | Detaches label and syncs with GitHub/Gitea |
updateDueDate |
ISO 8601 date string or null |
Sets or clears due dates |
After successful execution, the controller calls publishEvent for each affected task, ensuring real-time UI synchronization across connected clients.
Frontend Architecture for Bulk Operations
The Kaneo web interface implements bulk actions through a coordinated system of React components, custom hooks, and fetchers.
Component: Bulk Toolbar
The Bulk Toolbar (apps/web/src/components/bulk-selection/bulk-toolbar.tsx) appears automatically when users select multiple tasks. It renders action buttons based on available operations and consumes the useBulkOperations hook.
Hook: useBulkOperations
Located at apps/web/src/hooks/mutations/task/use-bulk-operations.ts, this hook creates a collection of useMutation objects—one for each bulk operation type. Key responsibilities include:
- Wrapping API calls with loading/error states
- Cache invalidation for
tasks,projects, andlabelsqueries on success - Returning strongly-typed
mutateAsyncfunctions for programmatic use
Fetcher: bulkOperation
The low-level network call resides in apps/web/src/fetchers/task/bulk-operation.ts. It sends a PATCH request and throws JavaScript exceptions for HTTP errors, allowing consistent error handling upstream.
Implementing Bulk Task Operations
React Hook Examples
Bulk archive (status update):
import { useBulkOperations } from "@/hooks/mutations/task/use-bulk-operations";
const { bulkArchive } = useBulkOperations();
async function archiveCompleted(taskIds: string[]) {
await bulkArchive(taskIds);
// Query cache automatically refreshes
}
Bulk assign to user:
const { bulkAssign } = useBulkOperations();
await bulkAssign({
taskIds: selectedIds,
userId: "usr_123abc"
});
Bulk add label:
const { bulkAddLabel } = useBulkOperations();
await bulkAddLabel({
taskIds: selectedIds,
labelId: "lbl_456def"
});
Direct Fetcher Usage (Non-React)
For server-side scripts, CLI tools, or vanilla JavaScript:
import bulkOperation from "@/fetchers/task/bulk-operation";
await bulkOperation({
taskIds: ["task_a1", "task_b2", "task_c3"],
operation: "updatePriority",
value: "high"
});
Importing Tasks with Bulk Operations
Kaneo does not expose a dedicated import endpoint. Instead, the recommended pattern combines task creation with bulk application of shared properties.
Import Workflow
- Parse source data (CSV, JSON, Trello export, etc.) on the client
- Create tasks individually using
createTaskfetcher (apps/web/src/fetchers/task/create-task.ts) - Collect returned task IDs
- Issue bulk operation to apply common labels, assignments, or due dates
This two-phase approach leverages Kaneo's existing validation while minimizing API calls for property application.
Import-Then-Bulk Example
import { createTask } from "@/fetchers/task/create-task";
import bulkOperation from "@/fetchers/task/bulk-operation";
async function importFromTrello(cards: TrelloCard[]) {
const newTaskIds: string[] = [];
// Phase 1: Create individual tasks
for (const card of cards) {
const { id } = await createTask({
title: card.name,
description: card.desc,
projectId: destinationProjectId
});
newTaskIds.push(id);
}
// Phase 2: Bulk-label all imports
await bulkOperation({
taskIds: newTaskIds,
operation: "addLabel",
value: "migrated-from-trello"
});
// Optional: Bulk assign to import owner
await bulkOperation({
taskIds: newTaskIds,
operation: "updateAssignee",
value: currentUserId
});
}
Key Implementation Files
| Purpose | Path |
|---|---|
| API route registration | apps/api/src/task/index.ts |
| Core bulk controller | apps/api/src/task/controllers/bulk-update-tasks.ts |
| Bulk toolbar UI | apps/web/src/components/bulk-selection/bulk-toolbar.tsx |
| Operations hook | apps/web/src/hooks/mutations/task/use-bulk-operations.ts |
| Network fetcher | apps/web/src/fetchers/task/bulk-operation.ts |
| List view integration | apps/web/src/components/list-view/task-row.tsx |
| Selection state | apps/web/src/store/bulk-selection.ts |
Summary
- Kaneo's bulk-task API at
/api/task/bulksupports seven operations: status, priority, assignee, delete, add/remove label, and due date updates - Workspace validation ensures users can only affect tasks within accessible workspaces
- Frontend integration uses
useBulkOperationshook with automatic cache invalidation - Import patterns combine individual task creation with bulk property application for efficiency
- Real-time sync via
publishEventkeeps all connected clients updated
Frequently Asked Questions
What is the payload limit for bulk operations?
The Kaneo source code does not enforce a hard limit on taskIds array length in bulk-update-tasks.ts, but practical limits depend on your database configuration and request timeout settings. For imports exceeding hundreds of tasks, consider batching into multiple requests.
Can I undo a bulk delete operation?
No. The delete operation permanently removes tasks immediately, with no soft-delete or trash mechanism in the current implementation. Always verify your selection before executing bulk deletions.
How do bulk operations handle partial failures?
The controller validates all task IDs against workspace membership before executing any database changes. If validation fails for any task, the entire request rejects with an error—operations are atomic at the request level.
Is there built-in CSV import support?
Not directly. Kaneo expects you to parse CSV files client-side and use the standard task creation API followed by bulk operations. This design keeps the core API lean while enabling flexible import sources (CSV, JSON, XML, third-party APIs).
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →