Checklists
Checklist tasks (checklist_items) are the individual to-dos attached to an offboarding record - "revoke GitHub access," "collect laptop," and so on. There's no standalone /checklists resource; tasks are created as a side effect of starting an offboarding and managed through the employee/offboarding endpoints below.
These are the same session-authenticated endpoints the PurpletGo web app uses (/api/employees, /api/checklist-templates) - not the API-key-based /api/v1 surface. If you're integrating from a server, you'll authenticate the same way the dashboard does.
How tasks get created
POST /api/employees
When you create an offboarding, its checklist is populated automatically. PurpletGo picks the task list in this order:
checklistTemplateIdin the request body, if you pass one explicitly- A role-based template configured under Settings → Role Templates, matched against the employee's role and separation type
- A shorter default list for contractors/vendors, or a general default list for regular employees
Each generated task has a task and an assignedTo. The default lists assign to IT Admin, HR, Manager, Employee and Finance; the contractor list also uses HR Admin. You can add more tasks afterwards with the add endpoint below, or by applying a template.
See the Offboarding API for the full create-offboarding request body.
Reading a checklist
Checklist items aren't fetched from their own endpoint - they come back embedded on the offboarding record.
GET /api/employees
Each row in the response includes a checklist_items array:
{
"id": "e3b0c442-...",
"employee_name": "Jordan Lee",
"checklist_items": [
{
"id": "f47ac10b-...",
"task": "Revoke GitHub access",
"completed": false,
"assigned_to": "IT Admin",
"due_date": null,
"sla_hours": 48,
"sla_deadline": "2024-06-03T10:00:00.000Z",
"sla_breached": false
}
]
}Field names are the raw checklist_items column names (snake_case) - there's no camelCase transformation on this endpoint.
Add a task
POST /api/employees/:offboardingId/checklist
Adds one task to an existing offboarding's checklist. Needs the offboardings_edit or checklists_manage permission (Super Admin, Admin, HR and Manager by default, or a custom role that grants either).
Request body
{ "task": "Collect parking pass", "assignedTo": "Facilities" }| Field | Required | Type | Description |
|---|---|---|---|
task | ✅ | string | 1 to 500 characters |
assignedTo | - | string | Free text, up to 100 characters. A missing or blank value is stored as HR - a task is never unassigned |
Response 201 Created - the new row, in the same snake_case shape as the embedded checklist:
{
"id": "f47ac10b-...",
"task": "Collect parking pass",
"completed": false,
"assigned_to": "Facilities",
"due_date": null,
"sla_hours": null,
"sla_deadline": null,
"sla_breached": false,
"not_needed_at": null,
"not_needed_reason": null
}Returns 404 if the offboarding isn't in your organisation (or your department scope), and 409 with "code": "case_completed" if the offboarding is already completed - its checklist can no longer change until it is moved back a stage. The addition is written to the audit log.
Update a task
PATCH /api/employees/checklist/:itemId
Updates one checklist item. This is also how you mark a task complete - there's no separate "complete" endpoint.
Request body (all fields optional - send only what you're changing)
| Field | Type | Description |
|---|---|---|
completed | boolean | Marking true stamps completed_at and clears any SLA breach; marking false clears completed_at. Requires the offboardings_edit permission |
notNeeded | boolean | true marks the task as not needed this time: it counts as completed but stays visible with its reason, and reason becomes required. false puts it back (and unticks it, unless you also send completed). Requires offboardings_edit |
reason | string | Why the task is not needed, 3 to 500 characters. Required when notNeeded is true, ignored otherwise |
task | string | Task description, 1 to 500 characters |
assigned_to | string | Who owns the task, up to 100 characters. A blank value is stored as HR |
due_date | date or null | YYYY-MM-DD |
sla_hours | integer or null | Hours from creation until the task is due (1 to 8760). Pass null to clear it |
Who can do what: ticking or unticking (completed) and notNeeded need offboardings_edit. Changing task, assigned_to, due_date or sla_hours needs offboardings_edit or checklists_manage, and setting (not clearing) sla_hours needs offboardings_edit. By default HR, managers and admins hold offboardings_edit; custom roles as the Roles screen shows. Anyone else gets 403.
Response 200 OK
{
"success": true,
"completed": true,
"slaHours": 48,
"slaDeadline": "2024-06-03T10:00:00.000Z",
"slaBreached": false,
"notNeededAt": null,
"notNeededReason": null
}Ticking a task that is already done (with nothing else in the body) changes nothing - completed_at and the automation that runs on completion are left alone - and returns { "success": true, "completed": true, "unchanged": true }.
Conflicts (409)
code | When |
|---|---|
case_completed | The offboarding is completed, so its checklist can no longer change. Move it back a stage first |
linked_item_open | The task follows another record (Revoke <app> access, Verify NDA) and completes itself from that record; ticking it by hand while the record still says otherwise is refused. error says what is still open. Marking it notNeeded is allowed |
Delete a task
DELETE /api/employees/checklist/:itemId
Removes a task outright. Use this for a task that should never have been on the list; a task that simply doesn't apply this time should be marked not needed with PATCH instead, which keeps it visible with its reason.
Needs the offboardings_edit or checklists_manage permission, plus a reason in the body. Deleting a task that is still open is an Admin decision: anyone else gets 403 with "code": "open_task_delete" and should mark it not needed instead.
Request body
{ "reason": "Duplicate of the IT access task" }| Field | Required | Type | Description |
|---|---|---|---|
reason | ✅ | string | 5 to 500 characters. Missing or out of range returns 400 with "code": "reason_required" |
Response 200 OK
{ "success": true }| Status | When |
|---|---|
403 open_task_delete | The task isn't completed and you aren't a Super Admin or Admin |
404 | No such task in your organisation or department scope |
409 case_completed | The offboarding is completed |
409 legal_hold | The offboarding is under legal hold (or was released less than 7 days ago); its checklist is part of the record |
The deletion is written to the audit log with the task, whether it was completed, and your reason.
Apply a checklist template
POST /api/checklist-templates/:id/apply/:offboardingId
Copies the template's items onto an already-created offboarding, on top of whatever tasks it already has. Items the offboarding already has (same task text, ignoring case and extra spaces) are skipped, so applying a template twice doesn't duplicate tasks.
Requires the checklistTemplates plan feature (Starter and up); on a plan without it the request returns 403 with "feature": "checklistTemplates" and "upgradeRequired": true.
Response 200 OK
{ "success": true, "itemsAdded": 6, "itemsSkipped": 2 }Returns 404 if the template isn't yours or the offboarding isn't in your organisation (or department scope), and 409 with "code": "case_completed" if the offboarding is already completed - the same rule as adding a task by hand. The apply is audited in the same transaction as the tasks it adds.
Templates themselves (GET/POST/PATCH/PUT/DELETE /api/checklist-templates) are managed separately - see Settings → Checklist Templates in the app for the full template CRUD surface.
Every template write - create, gallery import, rename (PATCH), full replace (PUT), duplicate, delete and apply - needs the checklists_manage permission: Super Admin and Admin by default, or a custom role that grants it. Anyone else gets 403.
SLA breach report
GET /api/employees/sla-breaches
Returns every incomplete task with an SLA configured, across all in-progress offboardings, sorted by deadline. Requires HR, manager, or admin permissions. Unlike the embedded checklist above, this endpoint camelCases its fields:
[
{
"id": "f47ac10b-...",
"task": "Revoke GitHub access",
"assignedTo": "IT Admin",
"slaHours": 48,
"slaDeadline": "2024-06-03T10:00:00.000Z",
"slaBreached": true,
"completed": false,
"dueDate": null,
"createdAt": "2024-06-01T10:00:00.000Z",
"offboardingId": "e3b0c442-...",
"employeeName": "Jordan Lee",
"employeeDepartment": "Engineering",
"exitDate": "2024-06-15",
"hoursOverdue": 6.2,
"hoursRemaining": 0,
"status": "breached"
}
]status is computed per-row: breached once the deadline has passed, at_risk when less than 25% of the SLA window remains, otherwise on_track.