API Reference

Projects

Manage projects represented by root tasks.

REST /api/v1API key authentication5 endpoints
GET/api/v1/projects

List 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/projects

Create 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/:id

Delete a project (soft delete)

Path parametersid: string
Response204No response body.
GET/api/v1/projects/:id

Get a single project

Path parametersid: string
Response200JSON response with a data envelope.
PATCH/api/v1/projects/:id

Update 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.