API Reference
Projects
Manage projects represented by root tasks.
REST /api/v1API key authentication5 endpoints
GET
/api/v1/projectsList projects (root tasks)
Query schema
const projectTypeSchema = z.enum(['client', 'admin', 'template']);
const versionStatusSchema = z.enum(['draft', 'baseline', 'contracted', 'active', 'archived']);
const listQuerySchema = z.object({
projectType: projectTypeSchema.optional(),
taskType: z.enum(['project', 'admin', 'template']).optional(),
status: versionStatusSchema.optional(),
contactId: z.string().uuid().optional(),
search: z.string().optional(),
limit: z.coerce.number().int().min(1).max(100).default(50),
offset: z.coerce.number().int().min(0).default(0),
});Response200JSON response with data and pagination envelopes.
POST
/api/v1/projectsCreate a new project (root task)
JSON body schema
const projectTypeSchema = z.enum(['client', 'admin', 'template']);
const createBodySchema = z.object({
code: z.string().optional(),
name: z.string().min(1),
contactId: z.string().uuid().optional(),
projectType: projectTypeSchema.optional(),
taskType: z.enum(['project', 'admin', 'template']).optional(),
taskTypeId: z.string().uuid().nullable().optional(),
isBillableRoot: z.boolean().optional(),
isPerpetual: z.boolean().optional(),
startDate: z.string().optional(),
endDate: z.string().optional(),
description: z.string().optional(),
tags: z.array(z.string()).optional(),
});Response201JSON response with a data envelope.
DELETE
/api/v1/projects/:idDelete a project (soft delete)
Path parametersid: string
Response204No response body.
GET
/api/v1/projects/:idGet a single project
Path parametersid: string
Response200JSON response with a data envelope.
PATCH
/api/v1/projects/:idUpdate a project
Path parametersid: string
JSON body schema
const projectTypeSchema = z.enum(['client', 'admin', 'template']);
const updateBodySchema = z.object({
code: z.string().optional(),
name: z.string().min(1).optional(),
contactId: z.string().uuid().nullable().optional(),
ownerResourceId: z.string().uuid().nullable().optional(),
projectType: projectTypeSchema.optional(),
taskTypeId: z.string().uuid().nullable().optional(),
isBillableRoot: z.boolean().optional(),
isPerpetual: z.boolean().optional(),
startDate: z.string().nullable().optional(),
endDate: z.string().nullable().optional(),
description: z.string().nullable().optional(),
color: z
.string()
.regex(/^#[0-9A-Fa-f]{6}$/, 'Invalid color format')
.nullable()
.optional(),
tags: z.array(z.string()).optional(),
});Response200JSON response with a data envelope.