HR and payroll
Import staff from a CSV file, make payroll files of approved timesheets by your own pay codes, and keep Agoo in step with your HR system.
This is a published preview. Names and fields may still change before general availability; changes will be listed in the changelog.
Agoo records when staff clock in and out, against their shifts and leave. These tools move that information to and from the systems your HR and payroll teams already use.
| Tool | What it does | Plans | Available |
|---|---|---|---|
| CSV staff import | Create and update people from a spreadsheet | Growth, Pro, Enterprise | Now, in the Console |
| Timesheet and payroll export | Approved hours and days by your own pay codes, per person and period, as CSV, Excel or your own layout, with corrections | Pro, Enterprise | Now, in the Console and the API |
| Attendance API | Read clock events, summaries and timesheets, and make and download payroll files, from your own systems | Pro, Enterprise | Now, as part of the preview |
| HR and payroll sync | Ongoing sync with your HR system, set up with our team | Enterprise | Planned |
Import staff from CSV
Admins import people in Console → People → Import CSV, starting from its Download template. The main columns:
| Column | Required | Notes |
|---|---|---|
full_name | Yes | Full name (a name column works too). |
email | Yes | Matches existing people, so re-importing updates rather than duplicates. |
role | Yes | A role name, such as Host, Employee or HR, or none for someone who doesn't sign in. |
sites | Yes | Site names exactly as in Settings → Sites. Separate several with ;. |
phone | No | A Ghana number such as 024 123 4567, or any number with its country code. |
department | No | Created if it doesn't exist. |
job_title | No | |
employee_id | No | Your HR or payroll system's ID for the person (an employee_number column works too). |
manager | No | Their line manager's email or employee ID: someone already in People, or earlier in the file. |
full_name,email,role,sites,phone,department,job_title,employee_id
Kwame Mensah,kwame.mensah@voltabank.example,Host,Ridge HQ,+233241234567,Treasury,Head of Treasury,VB-0142
Nii Armah,nii.armah@voltabank.example,Employee,Tema Branch,0205550142,Operations,Operations Officer,VB-0377Save the file as UTF-8 CSV so names with accents or other characters survive. The import shows a preview of what will be created and updated before anything changes. Every column, including attendance, start dates, employment type and contracted hours, is in Invite your team. The planned CLI's agoo people import will take the same file.
Set employee_id for everyone who appears on payroll. It's how your payroll team will match Agoo's export to their records, where it's the employee number.
Export timesheets for payroll
On Pro and Enterprise, HR, Owners and Admins make payroll files in Attendance → Payroll in the Console. A file covers one timesheet period, for the whole organisation or chosen sites, and holds only approved, locked timesheets; Agoo lists who isn't in it and why. Choose CSV, or Excel (.xlsx), and a layout: long, wide or one of your own. The guide Export for payroll walks through it. Your own systems can make and download the same files with the API.
Pay codes
Every line in a payroll file has a pay code. Each organisation names its own and sets each one's multiplier, starting from these defaults:
| Kind of time | Default code | Multiplier | Unit |
|---|---|---|---|
| Regular hours | REG | 1.0 | hours |
| Overtime, daily, and overtime, weekly | OT | 1.5 | hours |
| Rest-day work | OTREST | 1.5 | hours |
| Public holiday worked | PHW | 2.0 | hours |
| Public holiday worked, casual and temporary staff (s.77) | PHW-S77 | 2.0 | hours |
| Public holiday, paid day off, and closed days | PH | 1.0 | days |
| Night time, where the organisation counts it | NIGHT | empty: payroll sets it | hours |
| Authorised absence, paid | ABS-PAID | 1.0 | days |
| Absence, unpaid or unauthorised | ABS-UNPAID | 0 | days |
| Annual leave paid out on leaving (s.30) | LV-PAYOUT | 1.0 | days |
| Extra time not approved, for information (left out at first) | XT-DECLINED | 0 | hours |
| Each leave type | Its own, such as LV-ANNUAL, LV-SICK, LV-MAT | 1.0 paid, 0 unpaid | days |
Multipliers run from 0 to 10, to two decimal places, or are empty when payroll sets the rate. A kind of time can be left out of payroll files altogether. Agoo refuses to make a file while any time in it has no code, or while one code covers things paid differently (hours and days, or different multipliers), and says which: nothing goes out as regular hours by default. Every kind of leave appears under its own code, private kinds such as sick and maternity leave included, which is why payroll files have their own scope.
Long layout
One row per person and pay code. The Pay codes sheet in Excel.
| Column | Example | Notes |
|---|---|---|
employee_number | VB-0377 | From People. Agoo warns about anyone without one, and still makes the file. |
name | Nii Armah | |
department | Operations | |
site | Tema Branch | From People. |
period_start | 2026-09-01 | The timesheet period. |
period_end | 2026-09-30 | A correction keeps its original period. |
pay_code | OT | Your code. |
category | Overtime, daily | The kind of time, in words. |
units | 6.50 | Hours to two decimal places, counted after unpaid breaks, or days to the half day. Can be below 0 in a correction. |
unit | hours | hours or days. |
multiplier | 1.5 | Empty when payroll sets the rate. |
correction | (empty) | Yes on a correction line: the difference from an earlier file for the same period. |
approved_by | Kwame Mensah | Who approved the timesheet's last step. |
approved_at | 2026-10-03 14:21 | In the organisation's time zone. |
export_id | payroll_export_01m5… | The file's ID, as in the API. |
Wide layout
One row per person: employee_number, name, department, site, period_start, period_end, correction, a column for each pay code in the file (empty when the person has none of it), then approved_by, approved_at and export_id. The By person sheet in Excel.
Excel sheets
An Excel file starts with the layout you chose, then has Pay codes (long), By person (wide), Days (each person's days: status, first in and last out, worked, regular, daily and weekly overtime, rest-day, holiday and night hours, extra time and its decision, paid, unpaid and nursing break minutes and where the unpaid break came from, minutes late and left early, leave and its code, and the holiday) and Notes (who made it and when, the period and payroll date, the sites, approvals, reopenings and their reasons, corrections and which file each corrects, who isn't in the file and why, kinds of time left out, people with no employee number, and how to read the units).
Your own layout
If your payroll system imports its own columns, build a layout once in the Console: one row per pay code or per person; the columns, in your order, with your own headings (employee number, name, email, department, job title, site, employment type, pay code, category, units, unit, multiplier, a column per pay code, period start, period end, period, payroll date, correction, approved by, approved at, export, or fixed text); the separator (comma, semicolon, tab or pipe); the date format (YYYY-MM-DD, DD/MM/YYYY or MM/DD/YYYY); hours as decimals (7.50) or hours and minutes (7:30); a header row or none; and a file name pattern from {org}, {period}, {starts}, {ends}, {export} and {layout}. An organisation can keep up to 20. CSV files in your own layout have Windows line endings and no byte-order mark. Ready-made layouts for payroll systems used in Ghana are planned, each made from that system's real import file.
Corrections
A file is never changed once made. If a person's figures for a period change afterwards (their timesheet reopened and approved again, or a leaver's balance moved), the next file for that period carries correction lines for them: the difference, marked correction, dated to the original period, and the earlier file is marked superseded for them. A second file for a period carries only what's new or changed. Kinds of time left out are left out of corrections too.
Before you send it to payroll
- Read the Notes sheet, or the file's details in the Console: who isn't in the file and why, and who has no employee number.
- Hours are decimal.
7.50is seven and a half hours, already net of unpaid breaks. Choose hours and minutes in your own layout if your payroll expects7:30. - Check the checksum if you pass files on: every file is kept with its SHA-256, and downloading it again gives the same bytes.
- Ghana public holidays are applied automatically:
PHWfor work on them,PHfor the paid day off.
Read attendance with the API
For a custom integration, for example a nightly job that loads attendance into your payroll database, use the API on Pro and Enterprise:
| Endpoint | Use it for | Scope |
|---|---|---|
GET /attendance/summary | Present, late, on leave and absent counts for each day, up to 31 days at a time | attendance:read |
GET /attendance/events | Every clock-in and clock-out, with method, device, time and late minutes | attendance:read |
GET /shifts | Shift patterns, with start and end times and grace periods | attendance:read |
POST /attendance/events | Record clock-ins and clock-outs from your own terminals | attendance:write |
GET /leave-types, GET /leave-requests | Your leave types, and leave asked for, approved, declined or cancelled | attendance:read |
GET /people/{person_id}/leave-balances | A person's balance for each kind of leave this leave year | attendance:read |
POST /leave-requests | Record leave from your HR system, approved at once | attendance:manage |
GET /timesheet-periods, GET /timesheets, GET /timesheets/{timesheet_id} | Each period, and each person's approved and locked hours for it, with every day | attendance:read |
POST /timesheets/{timesheet_id}/approve, POST …/reopen | Approve a timesheet from your payroll system, or reopen one with a reason | attendance:manage |
GET /roster-shifts | The shifts on your rosters, by site, person and dates, including open ones | attendance:read |
POST /roster-shifts, POST /rosters/publish | Plan shifts from your workforce system as drafts, then publish a site's roster | attendance:manage |
GET /shift-swaps, GET /shift-claims | Swaps between staff and claims for open shifts, with where each approval stands | attendance:read |
GET /payroll-exports, GET /payroll-exports/{payroll_export_id} | The payroll files made, filtered by period_id, each with its period, sites, format, layout, counts and checksum | attendance:payroll |
POST /payroll-exports | Make a payroll file for a period (period_id, optional site_ids, format csv or xlsx, layout long or wide, note) | attendance:payroll |
GET /payroll-exports/{payroll_export_id}/file | Download a payroll file: the kept one, or a copy in another format or layout made from its lines | attendance:payroll |
Webhooks tell you as things happen: attendance.clocked_in, attendance.clocked_out, attendance.late, and attendance.voided when a punch stops counting; leave.requested, leave.approved, leave.declined and leave.cancelled for leave; timesheet.submitted, timesheet.approved and timesheet.reopened for timesheets; payroll_export.created when a payroll file is made, in the Console or through the API. Pay from timesheet.approved: an approved timesheet is locked, so its totals don't change unless it's reopened, which fires timesheet.reopened and later a new timesheet.approved. roster.published tells you a site's roster changed, and shift_swap.approved and shift_claim.approved that a shift moved to someone else, so your payroll or workforce system can follow the roster. Private kinds of leave, such as sick leave, come as away, never with what they are, except in payroll files, which name every kind by its pay code and so need their own scope, attendance:payroll. Punches a manager added or corrected in the Console have the method manual, with who added them and why; a corrected time voids the wrong punch and adds the right one, so drop voided punches from your records. To pay from Agoo's own files, wait for a period's timesheets to be approved, then POST /payroll-exports with an Idempotency-Key and download its file; make another for the same period after a timesheet.reopened and its new timesheet.approved, and it carries only the corrections. The API makes files in the long and wide layouts; your own layouts and the pay codes are set in the Console. The payroll export itself is Pro's and Enterprise's, so these calls return plan_required for an organisation on another plan, in test mode too. The recipe attendance to payroll is a complete example. Fields are described in the API reference.
HR and payroll sync
HR and payroll sync is planned. On Enterprise, our team will set up an ongoing sync with your HR or payroll system, so that joiners, leavers and department changes flow into Agoo, and attendance flows back, without anyone exporting files. What's possible will depend on your system and how it can be reached; talk to us about yours.
If your organisation uses Microsoft Entra ID or another SCIM-capable directory as its source of truth for staff, SCIM provisioning on Pro, also planned, will give you the people half of this.
Privacy
Attendance records are personal data under the Data Protection Act, 2012 (Act 843). Payroll files include only the columns above: no face templates, photos or locations. They name every kind of leave, private kinds included, so only HR, Owners and Admins, and integrations with attendance:payroll, can make or download them; someone whose role covers some sites only makes and sees files for those sites. Making a file, and every download, is recorded in the audit trail. Agoo keeps each file with your attendance records; keep the copies you download only as long as payroll needs them.