Payroll API
Auto-generated from the OpenAPI spec. Run
node docs-site/scripts/fetch-openapi.jsto regenerate.
POST /api/v1/staff-pay-components
Create Staff Pay Component
Create a pay component for a staff member. Manager-only.
Rejects a duplicate active component_type for the same user with 409. Requires salary_period when component_type='fixed_salary' (and rejects it for every other type, since it's meaningless there).
Request body
| Field | Required | Type | Description |
|---|---|---|---|
user_id | Yes | integer | |
component_type | Yes | string | |
rate | Yes | number | |
salary_period | No | string |
Responses
- 201 — Successful Response
- 422 — Validation Error
GET /api/v1/staff-pay-components
List Staff Pay Components
List pay components, optionally filtered by staff member. Manager-only.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
user_id | query | No |
Responses
- 200 — Successful Response
- 422 — Validation Error
PUT /api/v1/staff-pay-components/{component_id}
Update Staff Pay Component
Update rate, salary_period, and/or is_active. Manager-only. component_type and user_id are immutable — deactivate and create a new component instead.
Also doubles as the reactivate path: passing is_active: true flips a
previously soft-deleted component back on (same generic-PUT-reactivation
convention as elsewhere in this codebase). Reactivating re-runs the same
duplicate-active-type check that create_staff_pay_component enforces —
a staff member may never have two simultaneously-active components of the
same component_type, and reactivation is just as capable of creating that
collision as creation is, so it can't be allowed to skip the check.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
component_id | path | Yes | integer |
Request body
| Field | Required | Type | Description |
|---|---|---|---|
rate | No | number | |
salary_period | No | string | |
is_active | No | boolean |
Responses
- 200 — Successful Response
- 422 — Validation Error
DELETE /api/v1/staff-pay-components/{component_id}
Deactivate Staff Pay Component
Deactivate a pay component (is_active=False). Manager-only. Soft-delete — never a real row delete.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
component_id | path | Yes | integer |
Responses
- 200 — Successful Response
- 422 — Validation Error
GET /api/v1/payroll-runs
List Payroll Runs
List payroll runs, newest first. Manager-only.
Responses
- 200 — Successful Response
POST /api/v1/payroll-runs
Create Payroll Run
Compute and persist a draft payroll run, walking every staff member's active pay components and computing each amount server-side.
Request body
| Field | Required | Type | Description |
|---|---|---|---|
period_start | Yes | string | |
period_end | Yes | string |
Responses
- 201 — Successful Response
- 422 — Validation Error
GET /api/v1/payroll-runs/{run_id}
Get Payroll Run
Get a payroll run by ID, with nested line items. Manager-only.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
run_id | path | Yes | integer |
Responses
- 200 — Successful Response
- 422 — Validation Error
POST /api/v1/payroll-runs/{run_id}/finalize
Finalize Payroll Run
Lock a draft payroll run. Finalized runs are immutable — this rejects if the run is already finalized.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
run_id | path | Yes | integer |
Responses
- 200 — Successful Response
- 422 — Validation Error
POST /api/v1/payroll-line-items/{item_id}/mark-paid
Mark Payroll Line Item Paid
Record that this amount was paid to the staff member externally (bank transfer, cash) — no real transfer happens here. Only allowed on line items belonging to a finalized run, since a draft run's amounts can still change.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
item_id | path | Yes | integer |
Request body
| Field | Required | Type | Description |
|---|---|---|---|
paid_notes | No | string |
Responses
- 200 — Successful Response
- 422 — Validation Error