taskview-api
v1.17.2
Published
TypeScript/JavaScript SDK for the [TaskView](https://taskview.tech) API. Provides a typed interface for managing goals, task lists, tasks, tags, kanban boards, team collaboration, and task dependencies.
Readme
TaskView API
TypeScript/JavaScript SDK for the TaskView API. Provides a typed interface for managing goals, task lists, tasks, tags, kanban boards, team collaboration, and task dependencies.
Installation
npm install taskview-api axiosaxios is a peer dependency — you provide your own configured instance.
Quick Start
import axios from 'axios';
import { TvApi } from 'taskview-api';
const $axios = axios.create({
baseURL: 'https://api.taskview.app',
});
$axios.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`;
const api = new TvApi($axios);You can change the base URL at any time:
api.setBaseUrl('https://other-api.example.com');Authentication
All API requests (except auth endpoints) require a Bearer token in the Authorization header. Below is how to obtain and manage tokens.
Login
With email or username and password:
const response = await $axios.post('/module/auth/login', {
login: '[email protected]', // email or username
password: 'securePassword123',
});
const { access, refresh, userData } = response.data;Passwordless login (email code):
// 1. Request a login code
await $axios.post('/module/auth/send-login-code', {
email: '[email protected]',
});
// 2. User receives a code via email, then submit it
const response = await $axios.post('/module/auth/login-by-code', {
email: '[email protected]',
code: '123456',
});
const { access, refresh, userData } = response.data;Using Tokens
Once you have the access token, pass it to TvApi via the axios instance:
import axios from 'axios';
import { TvApi } from 'taskview-api';
const $axios = axios.create({
baseURL: 'https://api.taskview.tech',
});
$axios.defaults.headers.common['Authorization'] = `Bearer ${access}`;
const api = new TvApi($axios);Store the refresh token securely (e.g. httpOnly cookie or secure storage). The access token has a short lifetime; the refresh token lives longer (up to 30 days).
Refreshing Tokens
When the access token expires the server returns 401 Unauthorized. Use the refresh token to obtain a new pair:
const response = await $axios.post('/module/auth/refresh/token', {
refreshToken: refresh,
});
const { access: newAccess, refresh: newRefresh } = response.data;
// Update the axios header with the new access token
$axios.defaults.headers.common['Authorization'] = `Bearer ${newAccess}`;Logout
await $axios.post('/module/auth/logout');
// Clear stored tokens on the client sideOAuth Providers
TaskView supports OAuth login via Google, GitHub, and Apple. Redirect the user to:
GET /module/auth/provider/google
GET /module/auth/provider/github
GET /module/auth/provider/appleAfter successful authentication the user is redirected back with a login code that can be exchanged for tokens via the login-by-code endpoint.
JWT Payload Structure
The decoded access token contains:
{
exp: number; // Expiration timestamp
id: number; // Token ID
type: 'jwt';
userData: {
id: number; // User ID
email: string;
login: string;
permissions: {
[key: string]: {
id: number;
name: string;
description: string;
};
};
};
}API Modules
The TvApi instance exposes the following modules:
| Module | Access | Description |
|---------------------|----------------------|----------------------------------------|
| Goals | api.goals | Create, update, delete, fetch goals |
| Goal Lists | api.goalLists | Task lists within a goal |
| Tasks | api.tasks | Full task CRUD, history, assignments |
| Tags | api.tags | Tag management and task tagging |
| Kanban | api.kanban | Columns, task ordering, pagination |
| Graph | api.graph | Task dependency edges |
| Collaboration | api.collaboration | Users, roles, permissions |
Goals
// Fetch all goals
const goals = await api.goals.fetchGoals();
// Create a goal
const goal = await api.goals.createGoal({
name: 'Sprint 1',
description: 'First sprint tasks',
color: '#4A90D9',
});
// Update a goal
await api.goals.updateGoal({
id: goal.id,
name: 'Sprint 1 (updated)',
archive: 0,
});
// Delete a goal
await api.goals.deleteGoal(goal.id);Goal Lists
Goal lists are task lists that belong to a goal.
// Fetch lists for a goal
const lists = await api.goalLists.fetchLists({ goalId: goal.id });
// Create a list
const list = await api.goalLists.createList({
goalId: goal.id,
name: 'Backlog',
description: 'Upcoming work',
});
// Update a list
await api.goalLists.updateList({
id: list.id,
name: 'Backlog (v2)',
});
// Delete a list
await api.goalLists.deleteList(list.id);Tasks
// Fetch tasks with pagination and filters
const tasks = await api.tasks.fetch({
goalId: goal.id,
componentId: list.id, // list ID, or -1401 for all tasks
page: 1,
showCompleted: 0, // 0 = hide completed, 1 = show
firstNew: 0, // 0 = oldest first, 1 = newest first
searchText: 'bug', // optional text search
filters: { // optional filters
selectedUser: 5,
priority: 1,
selectedTags: { '12': true, '15': true },
},
});
// Create a task
const task = await api.tasks.createTask({
goalId: goal.id,
description: 'Fix login bug',
priorityId: 1, // 1 = low, 2 = medium, 3 = high
goalListId: list.id,
note: 'Details here',
startDate: '2025-03-01',
endDate: '2025-03-05',
});
// Update a task
await api.tasks.updateTask({
id: task.id,
description: 'Fix login bug (critical)',
complete: true,
priorityId: 3,
});
// Delete a task
await api.tasks.deleteTask(task.id);
// Fetch a single task by ID
const single = await api.tasks.fetchTaskById(task.id);
// Toggle user assignment
await api.tasks.toggleTasksAssignee({
taskId: task.id,
userId: 42,
});
// Task history
const history = await api.tasks.fetchTaskHistory(task.id);
await api.tasks.recoveryTaskHistory(history.history[0].historyId, task.id);Tags
// Fetch all tags
const tags = await api.tags.fetchAllTagsForUser();
// Create a tag
const tag = await api.tags.createTag({
name: 'urgent',
color: '#FF0000',
goalId: goal.id,
});
// Toggle tag on a task (adds if missing, removes if present)
await api.tags.toggleTag({ tagId: tag.id, taskId: task.id });
// Update a tag
await api.tags.updateTag({ id: tag.id, name: 'critical', color: '#CC0000' });
// Delete a tag
await api.tags.deleteTag({ tagId: tag.id });Kanban
// Fetch all columns for a goal
const columns = await api.kanban.fetchAllColumns(goal.id);
// Add a column
const column = await api.kanban.addColumn({
goalId: goal.id,
name: 'In Progress',
});
// Fetch tasks for a column (cursor-based pagination)
const result = await api.kanban.fetchTasksForColumn(goal.id, column.id, null);
// result.tasks, result.nextCursor, result.columnVersion
// Move a task between columns / reorder
await api.kanban.updateTasksOrderAndColumn({
goalId: goal.id,
columnId: column.id,
taskId: task.id,
prevTaskId: null,
nextTaskId: 10,
});
// Update a column
await api.kanban.updateColumn({ id: column.id, goalId: goal.id, name: 'Review' });
// Delete a column
await api.kanban.deleteColumn({ id: column.id, goalId: goal.id });Graph (Task Dependencies)
// Add a dependency edge (source -> target)
const edge = await api.graph.addEdge({ source: 1, target: 2 });
// Fetch all edges for a goal
const edges = await api.graph.fetchAllEdges(goal.id);
// Delete an edge
await api.graph.deleteEdge(edge.id);Collaboration
// Invite a user by email
await api.collaboration.inviteUserToGoal({
goalId: goal.id,
email: '[email protected]',
});
// Fetch goal members
const members = await api.collaboration.fetchUsersForGoal(goal.id);
// Remove a user
await api.collaboration.deleteUserFromGoal({
goalId: goal.id,
userId: 5,
});
// Roles
const roles = await api.collaboration.fetchRolesForGoal(goal.id);
const newRole = await api.collaboration.createRoleForGoal({
goalId: goal.id,
name: 'Developer',
});
await api.collaboration.toggleUserRoles({
goalId: goal.id,
userId: 5,
roleId: newRole.id,
});
// Permissions
const allPermissions = await api.collaboration.fetchAllPermissions();
await api.collaboration.toggleRolePermission({
goalId: goal.id,
roleId: newRole.id,
permissionId: 3,
});
await api.collaboration.deleteRoleFromGoal({
goalId: goal.id,
roleId: newRole.id,
});Permissions
The package exports TvPermissions — a map of all permission constants:
import { TvPermissions } from 'taskview-api';
TvPermissions.GOAL_CAN_DELETE // 'goal_can_delete'
TvPermissions.GOAL_CAN_EDIT // 'goal_can_edit'
TvPermissions.GOAL_CAN_MANAGE_USERS // 'goal_can_manage_users'
TvPermissions.GOAL_CAN_WATCH_CONTENT // 'goal_can_watch_content'
TvPermissions.GOAL_CAN_ADD_TASK_LIST // 'goal_can_add_task_list'
TvPermissions.COMPONENT_CAN_DELETE // 'component_can_delete'
TvPermissions.COMPONENT_CAN_EDIT // 'component_can_edit'
TvPermissions.COMPONENT_CAN_WATCH_CONTENT // 'component_can_watch_content'
TvPermissions.COMPONENT_CAN_ADD_TASKS // 'component_can_add_tasks'
TvPermissions.TASK_CAN_DELETE // 'task_can_delete'
TvPermissions.TASK_CAN_EDIT_DESCRIPTION // 'task_can_edit_description'
TvPermissions.TASK_CAN_EDIT_STATUS // 'task_can_edit_status'
TvPermissions.TASK_CAN_EDIT_NOTE // 'task_can_edit_note'
TvPermissions.TASK_CAN_EDIT_DEADLINE // 'task_can_edit_deadline'
TvPermissions.TASK_CAN_EDIT_TAGS // 'task_can_edit_tags'
TvPermissions.TASK_CAN_EDIT_PRIORITY // 'task_can_edit_priority'
TvPermissions.TASK_CAN_ASSIGN_USERS // 'task_can_assign_users'
TvPermissions.TASK_CAN_ACCESS_HISTORY // 'task_can_access_history'
// ... and more
TvPermissions.KANBAN_CAN_MANAGE // 'kanban_can_manage'
TvPermissions.KANBAN_CAN_VIEW // 'kanban_can_view'
TvPermissions.GRAPH_CAN_MANAGE // 'graph_can_manage'
TvPermissions.GRAPH_CAN_VIEW // 'graph_can_view'Build Formats
The library ships in three formats:
- ES Module —
taskview-api.es.js - CommonJS —
taskview-api.cjs.js - UMD —
taskview-api.umd.js - TypeScript declarations —
index.d.ts
Example
import axios from 'axios';
import { TvApi } from 'taskview-api';
const BASE_URL = 'http://localhost:1401';
const $axios = axios.create({ baseURL: BASE_URL });
async function login(): Promise<{ access: string; refresh: string }> {
const { data } = await $axios.post('/module/auth/login', {
login: '[email protected]',
password: 'user1!#Q',
});
return data;
}
async function main() {
// 1. Authenticate
console.log('Logging in...');
const { access, refresh } = await login();
console.log('Logged in. Access token received.');
// 2. Set auth header and create API instance
$axios.defaults.headers.common['Authorization'] = `Bearer ${access}`;
const api = new TvApi($axios);
// 3. Goals
console.log('\n--- Goals ---');
const goals = await api.goals.fetchGoals();
console.log(`Found ${goals.length} goal(s)`);
const goal = await api.goals.createGoal({
name: `Example Goal ${Date.now()}`,
description: 'Created by taskview-api example',
color: '#4A90D9',
});
console.log(`Created goal: id=${goal!.id}, name="${goal!.name}"`);
// 4. Goal Lists
console.log('\n--- Goal Lists ---');
const list = await api.goalLists.createList({
goalId: goal!.id,
name: 'Backlog',
description: 'Example task list',
});
console.log(`Created list: id=${list!.id}, name="${list!.name}"`);
const lists = await api.goalLists.fetchLists({ goalId: goal!.id });
console.log(`Goal has ${lists.length} list(s)`);
// 5. Tasks
console.log('\n--- Tasks ---');
const task1 = await api.tasks.createTask({
goalId: goal!.id,
description: 'First task',
priorityId: 1,
goalListId: list!.id,
});
console.log(`Created task: id=${task1!.id}, "${task1!.description}"`);
const task2 = await api.tasks.createTask({
goalId: goal!.id,
description: 'Second task (high priority)',
priorityId: 3,
goalListId: list!.id,
note: 'This is an important task',
});
console.log(`Created task: id=${task2!.id}, "${task2!.description}"`);
const tasks = await api.tasks.fetch({
goalId: goal!.id,
componentId: list!.id,
page: 1,
showCompleted: 0,
firstNew: 0,
});
console.log(`Fetched ${tasks.length} task(s) from list`);
// 6. Update a task
await api.tasks.updateTask({
id: task1!.id,
description: 'First task (updated)',
complete: true,
});
console.log(`Marked task ${task1!.id} as complete`);
// 7. Tags
console.log('\n--- Tags ---');
const tag = await api.tags.createTag({
name: 'example-tag',
color: '#FF5733',
goalId: goal!.id,
});
console.log(`Created tag: id=${tag!.id}, name="${tag!.name}"`);
await api.tags.toggleTag({ tagId: tag!.id, taskId: task2!.id });
console.log(`Added tag "${tag!.name}" to task ${task2!.id}`);
// 8. Kanban
console.log('\n--- Kanban ---');
const column = await api.kanban.addColumn({
goalId: goal!.id,
name: 'In Progress',
});
console.log(`Created kanban column: id=${column.id}, name="${column.name}"`);
const columns = await api.kanban.fetchAllColumns(goal!.id);
console.log(`Goal has ${columns.length} kanban column(s)`);
// 9. Graph (task dependencies)
console.log('\n--- Graph ---');
const edge = await api.graph.addEdge({
source: task1!.id,
target: task2!.id,
});
console.log(`Created dependency: task ${edge.fromTaskId} → task ${edge.toTaskId}`);
const edges = await api.graph.fetchAllEdges(goal!.id);
console.log(`Goal has ${edges.length} dependency edge(s)`);
// 10. Cleanup
console.log('\n--- Cleanup ---');
await api.graph.deleteEdge(edge.id);
console.log('Deleted dependency edge');
await api.kanban.deleteColumn({ id: column.id, goalId: goal!.id });
console.log('Deleted kanban column');
await api.tags.deleteTag({ tagId: tag!.id });
console.log('Deleted tag');
await api.tasks.deleteTask(task2!.id);
await api.tasks.deleteTask(task1!.id);
console.log('Deleted tasks');
await api.goalLists.deleteList(list!.id);
console.log('Deleted list');
await api.goals.deleteGoal(goal!.id);
console.log('Deleted goal');
console.log('\nDone! All examples completed successfully.');
}
main().catch((err) => {
console.error('Error:', err.response?.data || err.message);
process.exit(1);
});
