Last updated 9 October 2026View as Markdown
One pay period
POST /v1/payroll/period Needs a keyOne pay period the way payroll software runs it: tax on a cumulative or week 1/month 1 code, employee and employer NI by category letter (directors on the annual earnings period), student loans and the NI earnings bands. Every case in HMRC's payroll test data runs through this endpoint.
Request
A JSON body. Fields not listed here are rejected.
| Field | Type | Description |
|---|---|---|
pay_frequency required | string | How often the employee is paid: monthly, four_weekly, two_weekly or weekly. One of monthly, four_weekly, two_weekly, weekly. |
period required | integer | The tax week or month for weekly and monthly pay, else the pay period number. Allowed: 1 to 52. |
tax_code required | string | The tax code on the payroll record, with W1 or M1 for the week 1/month 1 basis. |
gross_pay required | number | Pay this period subject to NI, which student loans are also worked on. Allowed: 0 or more, under 100,000,000. |
tax_year optional | string | The tax year, such as 2026-27. The latest when not given. Default "2026-27". |
taxable_pay optional | number | Pay this period subject to tax, payrolled benefits included; gross_pay when not given. Allowed: more than -100,000,000, under 100,000,000. |
payrolled_benefits optional | number | Payrolled benefits in kind in taxable_pay: taxed, but outside the 50% limit. Allowed: 0 or more, under 100,000,000. |
taxable_pay_to_date optional | number | Taxable pay in this employment in earlier periods of the year. Allowed: more than -100,000,000, under 100,000,000. Default 0. |
tax_to_date optional | number | Tax deducted in this employment in earlier periods of the year. Allowed: more than -100,000,000, under 100,000,000. Default 0. |
ni_category optional | string | National Insurance category letter: A when not given. One of A, B, C, D, E, F, H, I, J, K, L, M, N, S, V, Z. Default "A". |
student_loans optional | array of string | Each loan the employee repays: plan_1, plan_2, plan_4, plan_5, postgraduate. One of plan_1, plan_2, plan_4, plan_5, postgraduate. Default []. |
director optional | object | A company director on the annual earnings period: NI this period is the year's NI on earnings to date less what earlier periods paid. |
director.earnings_to_date required in director | number | NI-able earnings as a director in earlier periods. Allowed: 0 or more, under 100,000,000. |
director.employee_ni_to_date required in director | number | Employee NI paid in earlier periods as a director. Allowed: 0 or more, under 100,000,000. |
director.employer_ni_to_date required in director | number | Employer NI paid in earlier periods as a director. Allowed: 0 or more, under 100,000,000. |
director.weeks_as_director optional | integer | Weeks as a director this year, when appointed during it (pro rata thresholds). Allowed: 1 to 52. |
Example
cURL
curl https://api.checktakehomepay.co.uk/v1/payroll/period \
-H "Authorization: Bearer $CHECKTAKEHOMEPAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"pay_frequency": "monthly",
"period": 1,
"tax_code": "1257L",
"gross_pay": 3000,
"student_loans": [
"plan_2"
]
}'Node.js
const response = await fetch('https://api.checktakehomepay.co.uk/v1/payroll/period', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHECKTAKEHOMEPAY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"pay_frequency": "monthly",
"period": 1,
"tax_code": "1257L",
"gross_pay": 3000,
"student_loans": [
"plan_2"
]
}),
});
const result = await response.json();Python
import os
import requests
response = requests.post(
"https://api.checktakehomepay.co.uk/v1/payroll/period",
headers={"Authorization": f"Bearer {os.environ['CHECKTAKEHOMEPAY_API_KEY']}"},
json={
"pay_frequency": "monthly",
"period": 1,
"tax_code": "1257L",
"gross_pay": 3000,
"student_loans": ["plan_2"],
},
)
result = response.json()Response
200, with the result and what produced it: tax_year, engine, hmrc_test_data, assumptions and sources. This is the example's real response. Every field's type is in the OpenAPI document.
200 OK
{
"tax_year": "2026-27",
"engine": "2026-27.1",
"hmrc_test_data": "rest of UK and Welsh tax v1.0, Scottish tax v1.1, NI v1.0, directors NI v1.0, student loans v1.0",
"tax_code": "1257L",
"tax": 390.2,
"tax_to_date": 390.2,
"regulatory_limit_applied": false,
"employee_ni": 156.16,
"employer_ni": 387.45,
"ni_earnings": {
"at_lower_earnings_limit": 559,
"lower_earnings_limit_to_primary_threshold": 489,
"primary_threshold_to_upper_earnings_limit": 1952
},
"student_loans": {
"plan_2": 49
},
"assumptions": [
"taxable_pay_to_date and tax_to_date are for this employment only, before this period."
],
"sources": [
"https://www.gov.uk/government/publications/payroll-technical-specifications-income-tax",
"https://www.gov.uk/government/publications/payroll-technical-specifications-national-insurance",
"https://www.gov.uk/government/publications/payroll-technical-specifications-student-loans/collection-of-student-loans-from-6-april-2026",
"https://www.gov.uk/government/publications/software-developers-payroll-test-data-2026-to-2027"
]
}Errors
- 400
INVALID_INPUT: the message names each field that is wrong. - 401
UNAUTHENTICATED(no key) orINVALID_KEY(a key we don’t know, or a revoked one).
Every code, and how to handle them: Errors.