Complete endpoint documentation for implementing the Task Manager backend.
Note: This document is for backend implementers. For integration examples, see README.md.
This micro-frontend delegates authentication to your parent application.
- Validate authentication keys/tokens in your backend
- Provide
userTypeandsessionIdto the task app via props - Secure all API endpoints - validate auth headers before processing
- Handle user login/logout in your application
All authenticated endpoints should include:
X-User-Type: public | friend | admin
X-Session-Id: <unique-session-identifier>Implement this interface for your storage backend:
interface TaskStorage {
getTasks(userType: UserType): Promise<TasksFile>
saveTasks(userType: UserType, tasks: TasksFile): Promise<void>
getStats(userType: UserType): Promise<StatsFile>
saveStats(userType: UserType, stats: StatsFile): Promise<void>
}Implementations:
- Cloudflare Workers KV
- Filesystem (Node.js)
- Database (SQL/NoSQL)
- In-memory (testing)
Get all active tasks for a board.
Query Parameters:
userType(optional):public|friend|adminboardId(optional): Board ID (default:main)
Response:
{
"tasks": [
{
"id": "01HQ...",
"title": "Task title",
"tag": "work home",
"state": "Active",
"createdAt": "2025-10-27T12:00:00Z",
"updatedAt": "2025-10-27T12:00:00Z",
"closedAt": null,
"startTime": "2025-10-27T14:00:00Z",
"endTime": "2025-10-27T15:00:00Z"
}
]
}Note: startTime and endTime are optional. Tasks without these fields are classic board tasks that won't appear in calendar views.
Create a new task.
Headers:
X-User-Type:public|friend|adminX-Session-Id: Session identifier
Body:
{
"title": "Task title",
"tag": "work",
"boardId": "main",
"startTime": "2025-10-27T14:00:00Z",
"endTime": "2025-10-27T15:00:00Z"
}| Field | Type | Required | Description |
|---|---|---|---|
title |
string | Yes | Task title |
tag |
string | No | Space-separated tags |
boardId |
string | No | Target board (default: "main") |
startTime |
string | null | No | Scheduled start time (ISO 8601) |
endTime |
string | null | No | Scheduled end time or deadline (ISO 8601) |
Response:
{
"id": "01HQ...",
"title": "Task title",
"tag": "work",
"createdAt": "2025-10-27T12:00:00Z",
"updatedAt": "2025-10-27T12:00:00Z",
"startTime": "2025-10-27T14:00:00Z",
"endTime": "2025-10-27T15:00:00Z"
}Update a task's title, tags, or scheduling.
Headers:
X-User-Type:public|friend|adminX-Session-Id: Session identifier
URL Parameters:
id: Task ID (ULID format)
Body:
{
"title": "Updated title",
"tag": "new-tag",
"boardId": "main",
"startTime": "2025-10-27T16:00:00Z",
"endTime": null
}| Field | Type | Required | Description |
|---|---|---|---|
title |
string | No | New task title |
tag |
string | No | New tags (space-separated) |
boardId |
string | No | Board ID (default: "main") |
startTime |
string | null | No | New start time (null to clear) |
endTime |
string | null | No | New end time (null to clear) |
Response:
{
"id": "01HQ...",
"title": "Updated title",
"tag": "new-tag",
"updatedAt": "2025-10-27T12:30:00Z",
"startTime": "2025-10-27T16:00:00Z",
"endTime": null
}Mark a task as completed (moves to stats graveyard).
Headers:
X-User-Type:public|friend|adminX-Session-Id: Session identifier
URL Parameters:
id: Task ID
Query Parameters:
boardId(optional): Board ID (default:main)
Example:
POST /task/api/01HQ.../complete?boardId=work
Response:
{
"ok": true,
"message": "Task 01HQ... completed"
}Permanently delete a task.
Headers:
X-User-Type:public|friend|adminX-Session-Id: Session identifier
URL Parameters:
id: Task ID
Query Parameters:
boardId(optional): Board ID (default:main)
Example:
DELETE /task/api/01HQ...?boardId=work
Response:
{
"ok": true,
"message": "Task deleted"
}Get all boards for the current user.
Query Parameters:
userType(optional):public|friend|adminsessionId(optional): Session identifier
Response:
{
"version": 1,
"updatedAt": "2025-10-27T12:00:00Z",
"boards": [
{
"id": "main",
"name": "Main Board",
"tags": ["work", "home"],
"tasks": [...],
"stats": {...}
}
]
}Create a new board.
Headers:
X-User-Type:public|friend|adminX-Session-Id: Session identifier
Body:
{
"id": "project-x",
"name": "Project X"
}Response:
{
"id": "project-x",
"name": "Project X",
"tags": [],
"tasks": []
}Delete a board and all its tasks.
Headers:
X-User-Type:public|friend|adminX-Session-Id: Session identifier
URL Parameters:
id: Board ID (cannot delete "main")
Response:
{
"success": true
}Error Response:
{
"error": "Cannot delete main board"
}Create a persisted tag on a board.
Headers:
X-User-Type:public|friend|adminX-Session-Id: Session identifier
URL Parameters:
id: Board ID
Body:
{
"tag": "urgent"
}Response:
{
"success": true,
"tags": ["urgent", "work", "home"]
}Delete a persisted tag from a board.
Headers:
X-User-Type:public|friend|adminX-Session-Id: Session identifier
Body:
{
"boardId": "main",
"tag": "urgent"
}Response:
{
"success": true,
"tags": ["work", "home"]
}Update tags for multiple tasks.
Headers:
X-User-Type:public|friend|adminX-Session-Id: Session identifier
Body:
{
"boardId": "main",
"updates": [
{ "taskId": "01HQ...", "tag": "urgent" },
{ "taskId": "01HR...", "tag": null }
]
}Response:
{
"success": true,
"updated": 2
}Move multiple tasks between boards.
Headers:
X-User-Type:public|friend|adminX-Session-Id: Session identifier
Body:
{
"sourceBoardId": "main",
"targetBoardId": "archive",
"taskIds": ["01HQ...", "01HR..."]
}Response:
{
"success": true,
"moved": 2
}Remove a specific tag from multiple tasks.
Headers:
X-User-Type:public|friend|adminX-Session-Id: Session identifier
Body:
{
"boardId": "main",
"tag": "urgent",
"taskIds": ["01HQ...", "01HR..."]
}Response:
{
"success": true,
"updated": 2
}Get user preferences (synced for non-public users).
Headers:
X-User-Type:public|friend|adminX-Session-Id: Session identifier
Response:
{
"version": 1,
"updatedAt": "2025-10-27T12:00:00Z",
"experimentalThemes": false,
"alwaysVerticalLayout": false
}Note: Theme is NOT included - it's stored per-device in sessionStorage.
Save user preferences (syncs for non-public users).
Headers:
X-User-Type:public|friend|adminX-Session-Id: Session identifier
Body:
{
"experimentalThemes": true,
"alwaysVerticalLayout": false
}Response:
{
"ok": true
}Validate an authentication key.
Note: Implement your own key validation logic. This endpoint is called when users enter a key in the settings modal.
Headers:
X-User-Key: user-provided-keyResponse (valid):
{
"valid": true
}Response (invalid):
{
"valid": false
}Create a new authenticated session after key validation.
Note: Called after successful key validation. Should create a server-side session and return session details.
Headers:
X-User-Key: validated-keyResponse:
{
"sessionId": "unique-session-identifier",
"userType": "friend",
"valid": true
}The frontend stores sessionId and userType in localStorage for subsequent requests.
Establish or migrate a session on page load (for authenticated users).
Note: Called on page load for non-public users. Used to migrate preferences from old sessions and establish the current session.
Headers:
X-User-Type: friend | admin
X-Session-Id: current-session-idBody:
{
"newSessionId": "current-session-id",
"oldSessionId": "previous-session-id-or-null"
}Response:
{
"success": true,
"sessionId": "current-session-id",
"userType": "friend",
"migrated": false,
"preferences": {
"experimentalThemes": false,
"alwaysVerticalLayout": false
}
}Important - Session Expiration: The
userTypefield in the response reflects the server's determined user type based on the current session state. If the server session has expired (e.g., KV TTL exceeded), the server will returnuserType: "public"even if the client sentX-User-Type: friend. The client must check for this mismatch and handle session expiration appropriately (show re-authentication prompt, reload page).
Get task statistics for a board.
Query Parameters:
userType(optional):public|friend|adminboardId(optional): Board ID (default:main)
Response:
{
"version": 2,
"counters": {
"totalCreated": 150,
"totalCompleted": 120,
"totalDeleted": 10,
"totalUpdated": 200
},
"graveyard": [
{
"id": "01HQ...",
"title": "Completed task",
"tag": "work",
"createdAt": "2025-10-20T10:00:00Z",
"closedAt": "2025-10-27T12:00:00Z",
"reason": "completed"
}
]
}All endpoints return errors in this format:
HTTP Status Codes:
200- Success400- Bad request (validation error)403- Forbidden (permission denied)404- Not found500- Server error
Error Response:
{
"error": "Error message describing what went wrong"
}interface Task {
id: string // ULID format
title: string
tag?: string // Space-separated tags
createdAt: string // ISO 8601
updatedAt: string // ISO 8601
closedAt?: string // ISO 8601 (when completed/deleted)
}interface Board {
id: string
name: string
tags: string[] // Persisted tags
tasks: Task[]
stats: StatsFile
}interface StatsFile {
version: number
counters: {
totalCreated: number
totalCompleted: number
totalDeleted: number
totalUpdated: number
}
graveyard: StatsTaskRecord[]
}For complete integration examples with Express, Hono, and Cloudflare Workers, see:
Related Documentation: