@worksection/api-client
v2.1.2
Published
API client library for Worksection
Readme
Worksection Node.js API Client
Official TypeScript/Node.js client library for the Worksection API.
Requirements
- Node.js 18+
- TypeScript 5+ (for TypeScript usage)
Installation
npm install @worksection/api-clientAuthentication
The client supports two authentication methods: API Key (admin access) and OAuth2 (user access).
API Key
Get your API key from your Worksection account settings.
import { Client } from '@worksection/api-client';
const client = new Client('https://your-account.worksection.com');
client.setApiKey('your-api-key');OAuth2
import { Client } from '@worksection/api-client';
const client = new Client('https://your-account.worksection.com');
client.setClient({
client_id: 'your-client-id',
client_secret: 'your-client-secret',
redirect_uri: 'https://your-app.com/callback',
scope: ['projects_read', 'tasks_read', 'tasks_write'],
// defaults:
auth_url: 'https://worksection.com/oauth2/authorize',
token_url: 'https://worksection.com/oauth2/token',
refresh_url: 'https://worksection.com/oauth2/refresh',
});
// Step 1: redirect the user to the authorization URL
const state = crypto.randomUUID();
const authUrl = client.oauth.getAuthorizationUrl(state);
res.redirect(authUrl);
// Step 2: exchange the authorization code for an access token (in your callback handler)
if (req.query.state !== state) throw new Error('Invalid state');
const token = await client.oauth.fetchAccessTokenByAuthCode(req.query.code);
client.setAccessToken(token);
// The client will automatically refresh the access token using the refresh token when needed.Available OAuth2 scopes
projects_read, projects_write, tasks_read, tasks_write, costs_read, costs_write,
tags_read, tags_write, comments_read, comments_write, files_read, files_write,
users_read, users_write, contacts_read, contacts_write, administrative
Usage
Projects
// List all projects
const projects = await client.projects.list();
// Filter projects: active | pending | archived
const active = await client.projects.list({ filter: 'active' });
// Get a single project
const project = await client.projects.get(projectId);
// Create a project
const project = await client.projects.create('Project title', {
email_manager: '[email protected]',
dateend: '2025-12-31',
});
// Update a project
const project = await client.projects.update(projectId, { title: 'New title' });
// Archive / activate
await client.projects.close(projectId);
await client.projects.activate(projectId);
// Manage members
await client.projects.addMembers(projectId, ['[email protected]']);
await client.projects.removeMembers(projectId, ['[email protected]']);
// Project groups (folders)
const groups = await client.projects.groups();
const group = await client.projects.createGroup('Group name');
// Tags
const tags = await client.projects.tags();
const tags = await client.projects.createTags(groupId, 'Tag name');
await client.projects.updateTags(projectId, [1, 2], [3]);
// Tag groups
const tagGroups = await client.projects.tagGroups();
const tagGroup = await client.projects.createTagGroup('Group name', 'public');
// Custom fields
const fields = await client.projects.customFields();Tasks
// List tasks in a project
const tasks = await client.tasks.list(projectId);
// List all tasks across all projects
const tasks = await client.tasks.list();
// Get a single task (with extra data)
const task = await client.tasks.get(taskId, { extra: 'text,files,comments' });
// Create a task
const task = await client.tasks.create(projectId, 'Task title', {
email_user_to: '[email protected]',
dateend: '2025-06-30',
priority: 'high',
});
// Create a subtask
const subtask = await client.tasks.create(projectId, 'Subtask title', {
id_parent: parentTaskId,
});
// Update a task
const task = await client.tasks.update(taskId, { title: 'New title' });
// Complete / reopen
await client.tasks.complete(taskId);
await client.tasks.reopen(taskId);
// Search tasks
const tasks = await client.tasks.search({ email_user_to: '[email protected]', status: 'active' });
// Subscribers
await client.tasks.subscribe(taskId, '[email protected]');
await client.tasks.unsubscribe(taskId, '[email protected]');
// Tags
const tags = await client.tasks.tags();
const tags = await client.tasks.createTags(groupId, 'Tag name');
await client.tasks.updateTags(taskId, [1, 2], [3]);
// Tag groups
const tagGroups = await client.tasks.tagGroups();
const tagGroup = await client.tasks.createTagGroup('Group name', 'public');
// Custom fields
const fields = await client.tasks.customFields();Comments
// List comments on a task
const comments = await client.comments.list(taskId);
// List comments with attached files
const comments = await client.comments.list(taskId, { extra: 'files' });
// Create a comment
const comment = await client.comments.create(taskId, 'Comment text', {
email_user_from: '[email protected]',
hidden: 1, // internal comment
});Members
// List all account members
const members = await client.members.list();
// Invite a new member
const member = await client.members.create('[email protected]', {
first_name: 'John',
last_name: 'Doe',
title: 'Developer',
role: 'user', // user | manager | admin
});
// Member groups (teams)
const groups = await client.members.groups();
const group = await client.members.createGroup('Backend Team');
// Work schedules
const schedules = await client.members.schedule({
users: ['[email protected]'],
datestart: '2025-01-01',
dateend: '2025-01-31',
});
await client.members.updateSchedule({
'[email protected]': { mon: 8, tue: 8, wed: 8, thu: 8, fri: 8 },
});User (OAuth2 only)
// Get the current authenticated user's profile
const profile = await client.user.profile();
// Timer management for the current user
const timer = await client.user.timer(); // get active timer (or null)
await client.user.startTimer(taskId); // start timer on a task
await client.user.stopTimer('Done for today'); // stop and log with a comment
await client.user.discardTimer(); // discard without loggingCosts
// List expense records
const costs = await client.costs.list();
// Filter by project, task, or date range
const costs = await client.costs.list({
id_project: projectId,
datestart: '2025-01-01',
dateend: '2025-01-31',
});
// Get totals/summary
const total = await client.costs.total({ id_project: projectId });
// Get totals broken down by project and task
const total = await client.costs.total({ extra: 'projects,tasks' });
// Create an expense record
const costId = await client.costs.create(taskId, {
time: 90,
money: 50,
email_user_from: '[email protected]',
comment: 'Design work',
date: '15.06.2025',
});
// Update / delete
await client.costs.update(costId, { time: 120, comment: 'Updated' });
await client.costs.delete(costId);Timers (admin)
// List all active timers across the account
const timers = await client.timers.all();
// Stop a specific timer
await client.timers.stop(timerId);Contacts
// List all contacts
const contacts = await client.contacts.list();
// Create a contact
const contact = await client.contacts.create('[email protected]', 'Jane Smith', {
title: 'CEO',
group: groupId,
phone: '+1 555 000 0000',
address: '123 Main St',
});
// Contact groups
const groups = await client.contacts.groups();
const group = await client.contacts.createGroup('VIP Clients');Events
// Get recent events for the whole account
const events = await client.events.list('7d');
// Get events for a specific project
const events = await client.events.list('30d', projectId);Files
// List files on a task or project
const files = await client.files.list({ id_task: taskId });
const files = await client.files.list({ id_project: projectId });
// Upload files
const uploaded = await client.files.upload(['/path/to/file.pdf']);
// Download a file
const downloaded = await client.files.download(fileId, '/path/to/save.pdf');Webhooks
// List all webhooks
const webhooks = await client.webhook.list();
// Create a webhook
// Available events: post_task, post_comment, post_project,
// update_task, update_comment, update_project,
// delete_task, delete_comment, close_task
const id = await client.webhook.create(
'https://your-app.com/webhook',
['post_task', 'update_task', 'close_task'],
{ projects: [projectId] },
);
// Delete a webhook
await client.webhook.delete(id);Error handling
import { ResponseException, UnauthorizedException } from '@worksection/api-client';
try {
const task = await client.tasks.get(taskId);
} catch (e) {
if (e instanceof UnauthorizedException) {
// Invalid or expired token
} else if (e instanceof ResponseException) {
// API returned an error response
console.error(e.message, e.statusCode);
}
}License
MIT
