API Reference

Resources

Manage staff resources, capacity, and organization membership records.

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

List resources with optional filters

Query schema
const listQuerySchema = z.object({
  isActive: z
    .string()
    .transform((v) => v === 'true')
    .optional(),
  roleId: z.string().uuid().optional(),
  disciplineId: z.string().uuid().optional(),
  homeOfficeId: z.string().uuid().optional(),
  skillGroupIds: z.array(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/resources

Create a new resource

JSON body schema
const salaryPeriodSchema = z.enum(['hour', 'day', 'week', 'month', 'year']);

const createBodySchema = z.object({
  name: z.string().min(1),
  email: z.string().email().optional(),
  phone: z.string().optional(),
  jobTitle: z.string().optional(),
  roleId: z.string().uuid().optional(),
  disciplineId: z.string().uuid().optional(),
  employmentType: z.string().optional(),
  startDate: z.string().optional(),
  endDate: z.string().optional(),
  countryCode: z.string().optional(),
  regionCode: z.string().optional(),
  homeOfficeId: z.string().uuid().optional(),
  skillGroupIds: z.array(z.string().uuid()).optional(),
  tags: z.array(z.string()).optional(),
  salary: z.number().min(0).optional(),
  salaryPeriod: salaryPeriodSchema.optional(),
  externalUserId: z.string().optional(),
});
Response201JSON response with a data envelope.
DELETE/api/v1/resources/:id

Delete a resource (soft delete)

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

Get a single resource

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

Update a resource

Path parametersid: string
JSON body schema
const salaryPeriodSchema = z.enum(['hour', 'day', 'week', 'month', 'year']);

const updateBodySchema = z.object({
  name: z.string().min(1).optional(),
  email: z.string().email().nullable().optional(),
  phone: z.string().nullable().optional(),
  jobTitle: z.string().nullable().optional(),
  roleId: z.string().uuid().nullable().optional(),
  disciplineId: z.string().uuid().nullable().optional(),
  employmentType: z.string().optional(),
  startDate: z.string().nullable().optional(),
  endDate: z.string().nullable().optional(),
  countryCode: z.string().nullable().optional(),
  regionCode: z.string().nullable().optional(),
  homeOfficeId: z.string().uuid().nullable().optional(),
  skillGroupIds: z.array(z.string().uuid()).optional(),
  tags: z.array(z.string()).optional(),
  isActive: z.boolean().optional(),
  salary: z.number().min(0).nullable().optional(),
  salaryPeriod: salaryPeriodSchema.nullable().optional(),
  externalUserId: z.string().nullable().optional(),
});
Response200JSON response with a data envelope.