Offboarding Initiations
An initiation is a request to start offboarding an employee, submitted by a manager (or HR/admin) and optionally routed through an approval chain before the real offboarding record gets created. This is a separate, earlier step from the Offboarding API - an initiation only becomes an offboarding once it's approved (or auto-approved).
Base path: /api/offboarding-initiations
This feature is gated behind the managerInitiation plan feature and is session-authenticated, like the rest of the app API - it is not part of the API-key-based /api/v1 surface.
Approval behavior
Whether an initiation needs approval at all depends on your org's settings and who's submitting it:
- If HR or an admin submits the request, it's auto-approved immediately and the offboarding is created on the spot.
- If your org has
require_initiation_approvalturned off, everything auto-approves the same way. - Otherwise, the initiation is routed through an approval chain: either the
chain_idyou pass explicitly, or the org'sdefault_chain_id. If neither resolves to a real chain, there's no formal chain - the request just sits pending and PurpletGo posts an interactive notification to Slack/Teams instead of routing through named steps.
Chains are made of ordered steps, each targeting either a specific approver_id or an approver_role. Approving a step advances current_step; approving the last step creates the offboarding. Steps can also be delegated to someone else. Chain configuration itself (creating/editing chains and their steps) lives under /api/approval-chains, not documented here.
Initiation object
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"org_id": "org_xyz",
"initiated_by": "usr_mgr001",
"initiated_by_name": "Alex Chen",
"initiated_by_email": "alex@acme.com",
"employee_name": "Jordan Lee",
"employee_email": "jordan.lee@acme.com",
"employee_role": "Senior Engineer",
"employee_department": "Engineering",
"exit_date": "2025-07-11",
"separation_type": "resignation",
"apps_to_revoke": ["github", "slack"],
"notes": "Employee has signed their resignation letter.",
"status": "pending",
"chain_id": "9c1e...",
"chain_name": "Standard Engineering Exit",
"current_step": 2,
"reviewed_by": null,
"reviewed_by_name": null,
"reviewed_at": null,
"rejection_reason": null,
"offboarding_id": null,
"created_at": "2025-06-26T10:30:00.000Z",
"updated_at": "2025-06-26T11:00:00.000Z"
}Status values: pending · approved · rejected. There's no cancelled status - withdrawing a pending initiation deletes it outright (see Withdraw).
Endpoints
Submit an initiation
POST /api/offboarding-initiations
Restricted to managers, HR, and admins.
Request body
{
"employee_name": "Jordan Lee",
"employee_email": "jordan.lee@acme.com",
"employee_role": "Senior Engineer",
"employee_department": "Engineering",
"exit_date": "2025-07-11",
"separation_type": "resignation",
"apps_to_revoke": ["github", "slack"],
"notes": "Employee has signed their resignation letter.",
"chain_id": null
}| Field | Required | Type | Description |
|---|---|---|---|
employee_name | Yes | string | Free-text name - there's no employee lookup by ID |
exit_date | Yes | date | ISO 8601 date (YYYY-MM-DD) |
employee_email | No | string | |
employee_role | No | string | |
employee_department | No | string | |
separation_type | No | enum | resignation · termination · layoff · retirement · contract_end · other. Defaults to resignation |
apps_to_revoke | No | string[] | Defaults to [] |
notes | No | string | Internal notes, max 2000 characters |
chain_id | No | uuid | Explicit approval chain to use instead of the org default |
Response 201 Created - the created initiation object. If it was auto-approved, status will already be "approved" and offboarding_id will be populated.
List initiations
GET /api/offboarding-initiations
Managers only see initiations they submitted; HR and admins see everything in the org.
Query parameters
| Parameter | Type | Description |
|---|---|---|
status | string | pending · approved · rejected |
limit | integer | Default 50, max 200 |
offset | integer | Row offset |
Response 200 OK
{
"rows": [ /* initiation objects */ ],
"total": 1,
"limit": 50,
"offset": 0
}Get an initiation
GET /api/offboarding-initiations/:id
Returns the initiation with a step_history array attached - one entry per approval step that's been reached, including who acted, when, and any notes or delegation.
Managers can only fetch their own initiations; HR/admins can fetch any.
Edit an initiation
PATCH /api/offboarding-initiations/:id
Only while status is pending, and only by the original submitter or HR/admin. Accepts any subset of the submit-time fields (employee_name, employee_email, employee_role, employee_department, exit_date, separation_type, apps_to_revoke, notes).
Approve an initiation
POST /api/offboarding-initiations/:id/approve
Request body
{ "comment": "Confirmed with finance. All clear to proceed." }The body key is notes, not comment - it's read straight off req.body.notes.
For chain-based initiations, only the designated approver (or role, or an active delegate) for the current step can call this - you'll get 403 otherwise, and 409 if that step was already acted on. Approving the final step creates the offboarding and sets status: "approved" with offboarding_id populated. For non-chain initiations, only HR/admins can approve.
Response 200 OK - the updated initiation. On the final approval, also includes offboarding_id.
Reject an initiation
POST /api/offboarding-initiations/:id/reject
Request body
{ "rejection_reason": "Incorrect employee record - please resubmit with corrected exit date." }rejection_reason is required. No offboarding is created; status becomes "rejected".
Delegate the current step
POST /api/offboarding-initiations/:id/delegate
Only meaningful for chain-based initiations - returns 400 if the initiation has no chain. Only the current step's designated approver can delegate, and not to the original initiator or to themself.
Request body
{ "delegate_id": "usr_hr002", "notes": "Out this week, please cover." }Response 200 OK
{ "delegated": true, "delegate_id": "usr_hr002", "step": 2 }Withdraw an initiation
DELETE /api/offboarding-initiations/:id
Only while status is pending, by the original submitter or HR/admin. Deletes the row outright.
Response 200 OK
{ "deleted": true }Approval settings
GET /api/offboarding-initiations/settings
{ "require_initiation_approval": true, "default_chain_id": "9c1e..." }PATCH /api/offboarding-initiations/settings
HR/admin only. Body: require_initiation_approval (boolean) and/or default_chain_id (uuid or null - must belong to your org).
HRIS integration example
A typical pattern for wiring an HRIS termination webhook to PurpletGo:
app.post('/webhooks/bamboohr', async (req, res) => {
const event = req.body;
if (event.type !== 'employee.terminated') return res.sendStatus(200);
await fetch('https://app.purpletgo.com/api/offboarding-initiations', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Cookie': sessionCookie, // this endpoint is session-authenticated, not API-key based
},
body: JSON.stringify({
employee_name: event.employeeName,
employee_email: event.employeeEmail,
exit_date: event.lastDay,
separation_type: 'termination',
notes: `BambooHR event ID: ${event.id}`,
}),
});
res.sendStatus(202);
});Related
- Offboarding API - the record that gets created once an initiation is approved
- Checklists - tasks generated automatically when the offboarding is created