Skip to main content

Payroll API

Auto-generated from the OpenAPI spec. Run node docs-site/scripts/fetch-openapi.js to 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

FieldRequiredTypeDescription
user_idYesinteger
component_typeYesstring
rateYesnumber
salary_periodNostring

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

NameInRequiredTypeDescription
user_idqueryNo

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

NameInRequiredTypeDescription
component_idpathYesinteger

Request body

FieldRequiredTypeDescription
rateNonumber
salary_periodNostring
is_activeNoboolean

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

NameInRequiredTypeDescription
component_idpathYesinteger

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

FieldRequiredTypeDescription
period_startYesstring
period_endYesstring

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

NameInRequiredTypeDescription
run_idpathYesinteger

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

NameInRequiredTypeDescription
run_idpathYesinteger

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

NameInRequiredTypeDescription
item_idpathYesinteger

Request body

FieldRequiredTypeDescription
paid_notesNostring

Responses

  • 200 — Successful Response
  • 422 — Validation Error