KalHR logo

API reference

Payroll

List a company's payroll runs, read a run's totals, and read each employee's pay in a run.

All three endpoints need Payroll: View. Amounts are in naira.

A payroll run is one company's pay for one pay date. Paying it is never available to a key: a person disburses it in KalHR, and the payroll.paid event tells you when every transfer has settled.

Payroll statuses

statusNumberMeaning
Draft, Pending2, 5Being prepared
PendingApproval4Waiting for approval
Active0Approved and ready to pay
Processing8Transfers are going out
Paid3Every transfer succeeded
Processed9Finished, but some transfers failed
Rejected7Rejected by an approver
InActive1Switched off

Abandoned runs are never returned.

List payroll runs

GET/v1/payroll/schedule/listKey needs Payroll: View

Returns one company's payroll runs, a page at a time, newest first.

Query parameters

ParameterTypeDefaultDescription
CompanyIduuidRequired. The company whose runs to list. Ids come from Companies.
PageNumberinteger1The page to return
PageSizeinteger25Runs per page
SearchTermstringPart of the payroll code
StartDate, EndDatedateOnly runs created on or between these dates
OrderByinteger10 oldest first, 1 newest first
GET v1/payroll/schedule/list
curl "https://api.kalhr.com/v1/payroll/schedule/list?CompanyId=1f2e3d4c-5b6a-4987-8a6b-5c4d3e2f1a0b" \
  -H "Authorization: Bearer $KALHR_API_KEY"

Response

{
  "isSuccessful": true,
  "code": "00",
  "message": "Success",
  "data": {
    "data": [
      {
        "id": "f00dbabe-2026-4e10-8a1b-c2d3e4f5a6b7",
        "payrollCode": "ACM-3F9A1C",
        "totalNumberOfEmployee": 134,
        "totalNetSalary": 48230115.75,
        "totalGrossSalary": 63500000,
        "paycycleId": 0,
        "paycycle": "Monthly",
        "status": "Paid",
        "payDate": "2026-10-25T00:00:00",
        "startDate": "2026-10-01T00:00:00",
        "dateCreated": "2026-10-20T11:42:09.117"
      }
    ],
    "pageNumber": 1,
    "pageSize": 25,
    "totalRecords": 10,
    "totalPages": 1
  }
}
FieldTypeDescription
id, payrollCodeuuid, stringThe run
totalNumberOfEmployeeintegerEmployees paid in the run
totalNetSalary, totalGrossSalarynumberTotals for the run
paycycleId, paycycleinteger, string0 Monthly, 1 SemiMonthly, 2 Weekly
statusstringSee statuses
payDate, startDatedatePay day, and the first day of its month
dateCreateddatetimeWhen the run was created (UTC)

Get a payroll run

GET/v1/payroll/schedule/{id}Key needs Payroll: View
GET v1/payroll/schedule/f00dbabe-2026-4e10-8a1b-c2d3e4f5a6b7
curl "https://api.kalhr.com/v1/payroll/schedule/f00dbabe-2026-4e10-8a1b-c2d3e4f5a6b7" \
  -H "Authorization: Bearer $KALHR_API_KEY"

Response

{
  "isSuccessful": true,
  "code": "00",
  "message": "Success",
  "data": {
    "id": "f00dbabe-2026-4e10-8a1b-c2d3e4f5a6b7",
    "numberOfEmployees": 134,
    "totalAllowance": 21800000,
    "totalDeduction": 9416884.25,
    "totalNetSalary": 48230115.75,
    "totalGrossSalary": 63500000,
    "totalPaye": 5853000,
    "created": "2026-10-20T11:42:09.117",
    "payDate": "2026-10-25T00:00:00",
    "startDate": "2026-10-01T00:00:00",
    "status": { "id": 3, "name": "Paid" }
  }
}

status is an object here: id is its number and name one of the statuses.

Get each employee's pay in a run

GET/v1/payroll/schedule/{id}/salariesKey needs Payroll: View

Returns one line per employee in the run, as a plain list (not paged).

GET v1/payroll/schedule/f00dbabe-2026-4e10-8a1b-c2d3e4f5a6b7/salaries
curl "https://api.kalhr.com/v1/payroll/schedule/f00dbabe-2026-4e10-8a1b-c2d3e4f5a6b7/salaries" \
  -H "Authorization: Bearer $KALHR_API_KEY"

Response

{
  "isSuccessful": true,
  "code": "00",
  "message": "Success",
  "data": [
    {
      "id": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
      "employeeId": "4b9d2c1e-7a3f-4e8b-9c21-5d6e7f8a9b0c",
      "employeeCode": "ACM-0042",
      "employeeName": "Ada Okafor",
      "grossSalary": 650000,
      "netSalary": 462340.5,
      "salary": 462340.5,
      "monthlyAllowance": 210000,
      "monthlyDeduction": 187659.5,
      "loanDeduction": 50000,
      "payePerMonth": 84120,
      "grossAnnual": 7800000,
      "netAnnual": 5548086,
      "totalAnnualAllowance": 2520000,
      "totalAnnualDeduction": 2251914,
      "payeAnnual": 1009440,
      "loans": [
        {
          "loanId": "1c2d3e4f-…",
          "amount": 600000,
          "monthlyRepayment": 50000,
          "totalRepayable": 600000,
          "totalRepaid": 250000,
          "outstandingBalance": 350000,
          "status": "Active",
          "nextDueDate": "2026-11-25T00:00:00Z",
          "installmentsRemaining": 7
        }
      ],
      "companyId": "1f2e3d4c-5b6a-4987-8a6b-5c4d3e2f1a0b",
      "organizationId": "8c1d0e2f-4a6b-4c8d-9e0f-1a2b3c4d5e6f",
      "dueDate": "2026-10-25T00:00:00Z",
      "isActive": true
    }
  ]
}
FieldTypeDescription
iduuidThis pay line (not the employee)
employeeId, employeeCode, employeeNameuuid, string, stringThe employee, their employee number and name
grossSalary, netSalarynumberPay for this run; salary repeats netSalary
monthlyAllowance, monthlyDeduction, payePerMonthnumberAllowances, deductions (including any loan repayment) and PAYE
loanDeductionnumberLoan repayment taken from this run
grossAnnual, netAnnual, totalAnnualAllowance, totalAnnualDeduction, payeAnnualnumberThe monthly figures × 12
loansarrayThe employee's approved, disbursed or active loans
dueDatedateThe run's pay day
  • Event catalogue: payroll.created, payroll.approved, payroll.paid, payroll.transfer_failed

Last updated October 19, 2026

Missing an endpoint or an event?

Tell us what you're building. The API grows from what integrators ask for.

See KalHR in action - 30 min demo