Payroll
Payroll data & automation
Payroll namespaces, pay run and payslip actions, settings and self-service endpoints, workflow events and reports.
Namespaces
All records are tenant scoped. See /reference/payroll for fields and filters.
| Namespace | Use it for |
|---|---|
payroll.PayrollPolicy | Currency, tax band basis, approval, GL accounts, optional organisation. |
payroll.PaySchedule | Who is paid together (all, departments, teams, employees, paySchemes), next pay date, automation, optional organisation. |
payroll.EarningPolicy, payroll.DeductionPolicy | Additions and deductions; optional organisation (empty = shared). |
payroll.EmployeeEarningPolicy, payroll.EmployeeDeductionPolicy | Policies assigned to one employee. |
payroll.GroupEarningPolicy, payroll.GroupDeductionPolicy | Policies assigned to a group. |
payroll.PayRun | A run for a schedule and period, with status and totals. |
payroll.PayRunLine | One employee's pay in a run, plus payslipSentAt and payslipSentTo. |
payroll.PayRunEarning, payroll.PayRunDeduction | What made up a line. |
payroll.PayRunAdjustment | One-off earnings or deductions for a run. |
hcm.PayScheme, hcm.PayGrade, hcm.PayGradeStep | Schemes of service, grades (with optional scheme) and steps. |
A pay run's status, totals and sign-off fields are read-only through the API: they change only through the actions below. The pay figures on a pay line are likewise set by calculation; a line accepts only notes.
Pay Run Actions
Instance consequences on payroll.PayRun (intent: "consequence", uniqueObject: { "id": … }):
| Consequence | From status | What it does |
|---|---|---|
calculate | Draft, Calculated | Pays everyone the schedule covers; the reply lists anyone skipped with a reason. |
approve | Calculated | Locks the figures. Restricted to the policy's approver or an administrator. |
reject | Calculated, Approved | Returns the run to draft. |
post | Approved (or Calculated when the policy needs no approval) | Marks the run paid and posts a balanced journal when GL accounts are mapped. |
void | Posted | Reverses the journal and voids the run. |
downloadPayslips | Calculated onwards | ZIP of PDFs. Optional lineIds. Over 20 payslips, the ZIP is emailed to the requester instead. |
sendPayslips | Approved, Posted | Emails payslips in the background. Optional lineIds, onlyUnsent. Replies with the number queued. |
downloadAdjustmentTemplate | Draft, Calculated | Excel template for bulk adjustments. |
importAdjustments | Draft, Calculated | Multipart upload of the filled template (file). |
downloadPaymentMandate | Calculated onwards | Excel payment mandate. |
1{
2 "__meta__": {
3 "namespace": "payroll.PayRun",
4 "schema": "model",
5 "intent": "consequence",
6 "consequence": "sendPayslips",
7 "sideEffects": { "consequenceType": "instance" },
8 "uniqueObject": { "id": 4 }
9 },
10 "onlyUnsent": true
11}On payroll.PayRunLine: downloadPayslip (one PDF) and sendPayslip (email it now; fails with a reason when the employee has no real email address).
On payroll.PaySchedule: createPayRun. Without dates it creates a run for the calendar month of the next pay date and moves the next pay date on.
On payroll.PayRunAdjustment: approve and reject, while the run is draft or calculated.
Controller Endpoints
namespace: "payroll.Payroll", schema: "controller":
| Intent | Who | Returns |
|---|---|---|
getSettings | Any signed-in user | scope (tenant or organisation), payslip email subject and message. |
updateSettings | Administrators | Saves the same fields. Switching to organisation fails until every active schedule has an organisation. |
getQuickStats | Payroll managers, administrators | Dashboard figures; pass organisationId to limit to one organisation. |
getPayRunSummary | Payroll managers, administrators | Run counts by status and totals for a year or month. |
getMyQuickStats | Any employee | Their own figures only. |
getMyPayslips | Any employee | Their payslips from posted runs. |
downloadMyPayslip | Any employee | One of their own payslips as a PDF (lineId). |
Workflow Events
Use these when building workflows:
payroll.PayRun:create,payroll.PayRun:update,payroll.PayRun:calculate,payroll.PayRun:approve,payroll.PayRun:reject,payroll.PayRun:post,payroll.PayRun:void,payroll.PayRun:import_adjustmentspayroll.PaySchedule:create,payroll.PaySchedule:update,payroll.PaySchedule:activate,payroll.PaySchedule:deactivate,payroll.PaySchedule:create_runpayroll.PayrollPolicy:create,payroll.PayrollPolicy:update,payroll.PayrollPolicy:activate,payroll.PayrollPolicy:deactivatepayroll.PayRunAdjustment:approve,payroll.PayRunAdjustment:rejectpayroll.EmployeeEarningPolicy:*,payroll.EmployeeDeductionPolicy:*,payroll.GroupEarningPolicy:*,payroll.GroupDeductionPolicy:*(activate,approve,deactivate)
Background Jobs
| Task | When | What it does |
|---|---|---|
src.payroll.tasks.process_automatic_pay_runs | Daily at 02:15 (scheduler service) | Creates pay runs for active auto-run schedules that are due, and calculates or approves them when the schedule says so. |
src.payroll.tasks.send_payslips | On sendPayslips | Emails payslips, records each send on its pay line, and emails the requester a summary. |
src.payroll.tasks.email_payslip_zip | On downloadPayslips over 20 payslips | Builds the ZIP in parts of up to 500 and emails it to the requester. |
Reports
Payroll reports live in the Reports app and can be restyled or extended:
- Payslip Report (
payroll.PayRunLine, PDF): the payslip. Download and email both use it. - Pay Run Summary Report (
payroll.PayRun, PDF). - Payment Mandate (
payroll.PayRun, Excel): net pay with bank details and one column per earning and deduction. - Bank Payment File and Payroll Summary Export (CSV).
- Earnings and Deductions reports (
payroll.PayRunEarning,payroll.PayRunDeduction).
Automation Ideas
- On
payroll.PayRun:calculate, create a task for the approver with the run's net total. - On
payroll.PayRun:approve, callsendPayslips, or wait untilpostif payslips should only go out once money moves. - On
payroll.PayRun:post, notify finance with the journal reference. - On
payroll.PayRunAdjustment:reject, notify whoever requested it.
Guardrails
- Integrations cannot set a run's status or totals directly; drive the lifecycle through the actions above.
- In per-organisation mode, give each integration's schedules an organisation and check the policies it creates are owned or shared correctly.
- Payslip email uses your workspace's mail settings; placeholder addresses are skipped, never sent to.