/v1 base path, directly under the gateway base URLs listed in the API reference introduction. All endpoint paths on this page are relative to that base path.
Key concepts
- Payroll configuration — a pay schedule that employees are assigned to. Every pay run belongs to exactly one payroll configuration, and an organisation can run several in parallel.
- Pay run — the processing of one pay period, identified by payroll configuration, tax year, and period. Locking a run finalises it.
- Pay element — an organisation-level definition of a pay item type (for example basic pay or overtime) that uploaded pay data refers to.
- Payroll line — a single pay item uploaded for an employee for a pay date. Payroll lines are the input to a pay run’s gross-to-net calculation.
- Payslip — the per-employee output of a pay run, retrievable individually, by pay run, or across a date range.
- Effective-dated records — tax codes, NI categories, working patterns, and SSP qualifying-day policies are stored with effective dates, so a change applies from a given date without losing history.
- FPS — the Full Payment Submission sent to HMRC for a specific pay run.
- EPS — the Employer Payment Summary for a tax month, submitted from monthly balances or manually.
- Year-end finalisation — closes a tax year for a payroll configuration once its final pay run is complete.
API structure
Organisation
Manage organisation information, HMRC settings, opening balances, year-to-date running balances, and PAYE liability, including recording the PAYE payments you make to HMRC.GET /organisation/information and POST /organisation/hmrc/settings are the starting points; organisation-wide working-pattern defaults live under /organisation/working-pattern-defaults. See the organisation setup guide for the product-side view.
Pay elements
Create, read, update, and delete the pay elements available to your organisation under/organisation/pay-element. Payroll lines reference these definitions.
Payroll configurations
Create and manage pay schedules withPOST /payrollconfig and its companions. A configuration can carry its own working-pattern defaults that override the organisation default. GET /payrollconfig/{payrollConfigId} returns hasPayRuns, which tells you whether the pay schedule is still editable before you offer the fields — see Pay schedule changes below. The pay run settings guide explains the equivalent product screens.
Employees
Full lifecycle management of employee records:POST /employees to create, GET /employees to list with pagination, plus lookups by National Insurance number and payroll ID. Working patterns, working schedules, and SSP qualifying-day policies are managed per employee as effective-dated records — see working patterns for how a pattern is resolved and what each kind means. See also managing people.
Tax codes, NI, and loans
Maintain each employee’s effective-dated tax codes and NI categories, update their NI number or payroll ID, and start or end student and postgraduate loans.GET /employees/{employeeId}/effective-tax-info returns the tax code and NI category in force on a given date.
Starters and leavers
Set starter details withPUT /employees/{employeeId}/starter, and set or cancel leaver details individually or in bulk via PUT /employees/leaver/bulk. See the onboarding and leavers guides.
Payroll runs and pay data
Upload pay data withPOST /payroll/line/{employeeId}, attach supporting documents to lines, and set employee opening balances and payroll-config assignments. Create a run for a specific period, or use POST /payroll/{payrollConfigId}/next to create the next one in sequence, then finalise it with POST /payroll/{payrollConfigId}/{year}/{period}/lock. Listing endpoints return runs by tax year and the employees included in a run.
Calculator
POST /calculator/grosstonet calculates gross-to-net values, including tax and NI, so you can preview figures before locking a run.
Payslips
Retrieve payslips for a whole pay run, for an employee in a period, or for an employee across a date range. You can also set payslip metadata such as notes and a payment-date overwrite, and send payslip notification emails withPOST /notification/email/payslip/{payrollConfigId}/{year}/{period}. See the payslips guide.
Reading pension on a payslip
A payslip reports pension in two places, and they describe the same money:forPeriod.pension(and the year-to-date and employment-to-date equivalents) is the member’s total pension movement for the slice: contributions deducted, including additional voluntary contributions, less any opt-out refunds paid back.summaryItemscarries one row per pension contribution, each classified bypensionLineType, for organisations using itemised pension contributions.
pensionLineType is the field to branch on. It is null on every non-pension item, so the presence of a contribution row is what tells you which source to use:
A refund is money going back to the employee, so it is a payable row with a positive
amount, and forPeriod.pension has it netted off already. Keep it out of your contribution total and subtract it separately if you need the member’s net movement for the period.
pensionRefundsByType on the same object breaks the period’s refunds down per scheme type, if you would rather read the totals than the rows.
Two more fields ride on those rows and are never additive:
pensionEmployerContributionis the employer contribution attributable to that line. It is already insideforPeriod.employerPension, so it is display metadata, not a separate cost.pensionMetadatarecords the context the row calculated under: the pension group, the contribution basis, the employer share, and acontributionSourcesaying whether the settings came from the group, a standing per-employee override, or an override for this pay run only.
Branch on
pensionLineType, not on anything about the organisation. A payslip calculated before an organisation’s pension setup changed still has to add up, and the rows on the payslip are the only thing that tells you how it was calculated.forPeriod.pension (which is 0 for a purely sacrifice arrangement) and lands in forPeriod.employerPension. The sacrifice itself has always appeared in summaryItems as a Contribution row, because that is how a payslip shows it. What is new for relief-at-source and net-pay-arrangement schemes is that their contributions now appear as rows too, where previously forPeriod.pension was the only place they showed up.
RTI
Trigger an FPS for a pay run withPOST /rti/fps/{payrollConfigId}/{taxYear}/{period} and retrieve its details. Submit an EPS from monthly balances or manually, resubmit a manual EPS, and list submissions by tax year. See the HMRC RTI guide.
Year end
Finalise year-end for a payroll configuration withPOST /payroll/year-end/{taxYear}/{payrollConfigId}/finalise, and read finalisations per configuration or across the organisation.
Typical workflow
- Set your organisation information and HMRC settings with
POST /organisation/informationandPOST /organisation/hmrc/settings. - Create a payroll configuration with
POST /payrollconfigand define your pay elements under/organisation/pay-element. - Add employees with
POST /employees, then set their starter details, tax codes, and NI categories. - Upload each employee’s pay data for the period with
POST /payroll/line/{employeeId}. - Preview the figures with
POST /calculator/grosstonetand resolve any validation issues reported on upload. - Lock the run with
POST /payroll/{payrollConfigId}/{year}/{period}/lock, then retrieve payslips for the run and email them to employees. The running a pay run guide covers the same flow in the product. - Submit the FPS for the run with
POST /rti/fps/{payrollConfigId}/{taxYear}/{period}, and submit the EPS for each tax month from monthly balances.
Notes and best practices
- Pagination —
GET /employeesacceptspageSize(1–100) andpaginationToken; pass the returned token to fetch the next page. - Payroll line uploads — each request accepts up to 100 lines. Lines that fail validation are reported back, and every accepted line’s response includes a
payrollDate: the date you supplied, or the next unlocked pay date if that date’s run is already locked. - Locking — locking creates the pay run record in a locked state for that configuration, tax year, and period. Upload and correct pay data before you lock.
- FPS request body —
POST /rti/fps/{payrollConfigId}/{taxYear}/{period}takes{ "finalSubmissionDetails": { ... }, "lateReason": "..." }, both optional.lateReasonis HMRC’s late reporting reason for an FPS sent after the payment date (codes A, B, C, D, F, G, H; the withdrawn code E is rejected) and is reported on every payment. Sending the final submission details object as the body itself is deprecated as input and stops being accepted on 15 January 2027; wrap it infinalSubmissionDetails. See Deprecations. - EPS corrections — a manual EPS can be resubmitted with
POST /rti/eps/{taxYear}/manual/{submissionId}/resubmitif HMRC rejects it or the figures change. - Opening balances — the flat NI totals on
openingBalanceDirectorand the aggregatepensiononopeningBalanceare deprecated as input and stop being accepted on 7 November 2026; sendniBandResultandpensionContributionsByTypeinstead. Both keep being returned on responses, so only what you send changes. See Deprecations. - Salary —
salaryis deprecated as input onPUTandPATCH /employees/{employeeId}, and stops being accepted on those two operations on 20 December 2026; record changes withPUT /employees/{employeeId}/salary, which keeps an effective-dated history.POST /employeesstill accepts it as the starting salary, and it keeps being returned on every response as the amount in force today, so only what you send changes. See Deprecations. - Pay schedule changes —
payFrequencyandpaymentPeriodConfigcan only be changed on a payroll configuration that has no pay runs. Once a run exists, of any status,PUT /payrollconfig/{payrollConfigId}refuses a change to either with a409and the tokenpayroll_config_has_pay_runs. Everything else on the configuration stays editable, and re-sending the two fields unchanged is always accepted, so a full-bodyPUTthat only renames the schedule still works.GET /payrollconfig/{payrollConfigId}returnshasPayRunsso you can show the fields as locked instead of waiting for the refusal; it is read-only and ignored if you send it back. - Payslip PDFs —
GET /payslip/data/{employeeId}/{year}/{period}/filereturns the payslip asapplication/pdf(sendAccept: application/pdf), with the file name inContent-Disposition. It is not password-protected; only the copy emailed to the employee is. - Pension totals: take pension from the
summaryItemsrows or fromforPeriod.pension, never from both. See reading pension on a payslip.
Authentication
Every request needs a bearer token in theX-Auth-Token header, and credentials with access to more than one organisation should also send X-Org-Id — see Authentication. All responses use the shared envelope described in Response format.