Documentation

VerityPay Documentation

Everything you need to run payroll, stay SARS-compliant, and manage your South African workforce.

Overview

VerityPay is South African payroll software designed for SARS compliance. It handles the full gross-to-net payroll pipeline including PAYE (annualised method), UIF, SDL, and ETI — and generates SARS-ready EMP201 XML and bank EFT files automatically.

Every customer account is an Organisation. All data — employees, payroll runs, leave records, documents — is strictly scoped to your organisation. No other customer can access your data.

SARS 2025/26 tax tables
Unlimited employee records
EMP201 & IRP5 generation
Bank EFT files (4 major banks)
AES-256 PII encryption
First payroll in under 1 hour

Getting Started

Set up VerityPay and run your first payroll in under an hour.

1

Register your organisation

Create an account at veritypay.co.za/register. Provide your organisation name, registration number, and PAYE reference number. Your organisation slug becomes part of your dashboard URL (e.g. /acme-corp).

2

Configure pay types

Go to Settings → Pay Types to define your salary components: basic salary, travel allowances, housing, commissions. Mark each as taxable or non-taxable. These become selectable when running payroll.

3

Add employees

Add employees manually via Employees → New Employee, or bulk-import via CSV (Growth plan and above). Each employee requires: SA ID or passport number, banking details, tax details, and employment start date.

4

Run your first payroll

Go to Payroll → New Run. Select the pay period and employees, enter gross earnings per pay type, then click Calculate. VerityPay computes PAYE, UIF, SDL, and ETI automatically.

5

Review, approve, and export

A second admin reviews and approves the run (two-person rule enforced by the system). Download payslips (PDF), bank EFT file (CSV), and EMP201 XML for SARS eFiling.

Core Concepts

Organisations

An Organisation is your company on VerityPay. It has a unique slug (e.g. acme-corp) used in all dashboard and portal URLs. All data is scoped to your organisation — employees, payroll runs, tax settings, and reports. Multiple admins can be invited with the Owner or Payroll Admin role.

Employees

Each employee record contains:

  • Identity: SA ID number or passport (AES-256 encrypted at rest)
  • Employment: start date, department, job title, employment type
  • Payroll profile: pay type allocations, UIF opt-out status where applicable
  • Banking: bank name, account number (AES-256 encrypted), account type
  • Tax: PAYE directive number if applicable, medical aid credits
  • Leave balances: annual, sick, and family responsibility days

Pay Types

Pay types are reusable income and deduction components configured per organisation. Examples: "Basic Salary" (taxable), "Travel Allowance" (partially taxable), "Medical Aid Employee Contribution" (deduction). Custom pay types are created in Settings → Pay Types.

Payroll Runs

A payroll run is an immutable record of one pay period. Once approved and completed it cannot be edited. Corrections are handled by creating a new correction run for the affected period. Each run records calculatedById and approvedById — these must be different users (two-person rule).

Payroll Processing

The payroll engine follows a strict gross-to-net pipeline to ensure SARS compliance and auditability.

Three Gross Definitions

SARS requires different income bases for different contributions:

Gross TypeIncludesUsed For
gross_for_payeAll taxable incomePAYE calculation
gross_for_uifBasic + regular commission + allowances — excludes bonuses and overtimeUIF calculation
gross_for_sdlEverything — no exclusionsSDL calculation

Two-Person Approval Rule

Every payroll run requires two different administrators: one to calculate and one to approve. The system enforces calculatedById ≠ approvedById at the database level. This mirrors South African corporate governance best practices and reduces payroll fraud risk.

Idempotency

Every financial operation is assigned an idempotency key stored in the database. Duplicate requests (e.g. double-submit due to network error) are safely de-duplicated and will not create double payments.

Tax Calculations

All tax calculations are implemented as pure, stateless functions with no database access or side effects — making them independently testable and auditable. SARS 2025/26 tables are used.

PAYE — Annualised Method

VerityPay uses the SARS-prescribed annualised method:

  1. Annualise monthly gross: monthly_gross × 12
  2. Find the applicable SARS tax bracket
  3. Apply: bracket_base + (annualised_gross − bracket_floor) × bracket_rate
  4. Subtract applicable rebates (primary, secondary, tertiary)
  5. Divide annual tax by 12 to get monthly PAYE

2025/26 Rebates

Primary (all taxpayers under 65)R17,235
Secondary (65–74 years)+ R9,444
Tertiary (75+ years)+ R3,145

2025/26 Tax-Free Thresholds

Below 65R95,750/year
65–74 yearsR148,217/year
75+ yearsR165,689/year

UIF

Unemployment Insurance Fund contributions are calculated at 1% employee + 1% employer, capped at R177.12/month each (ceiling remuneration R17,712/month). UIF excludes bonuses, overtime pay, retrenchment pay, and retirement lump sums.

SDL

Skills Development Levy is 1% employer only, payable if your organisation's total annual payroll exceeds R500,000. SDL applies to all remuneration with no exclusions. VerityPay tracks your rolling annual payroll and applies SDL only once the threshold is crossed.

ETI

Employment Tax Incentive reduces the employer's monthly PAYE liability for qualifying employees. Qualifying criteria: aged 18–29, earning R2,000–R6,500 per month, within first 24 months of employment at your organisation, employer not in default with SARS. VerityPay automatically identifies qualifying employees and calculates the ETI reduction each month.

Leave Management

VerityPay implements full BCEA (Basic Conditions of Employment Act) leave. Balances accrue monthly and are tracked per employee.

Leave TypeEntitlementCarry OverNotes
Annual15 working days/yearYesAccrues monthly. Paid out on termination (taxable, IRP5 code 3606).
Sick30 days / 3-year cycleWithin cycleResets at start of new 3-year cycle from employment date.
Family Responsibility3 days/yearNoResets on employment anniversary. Not carried over or paid out.

On termination, VerityPay automatically calculates outstanding annual leave and adds it as a taxable line item on the final payslip (IRP5 code 3606, as required by SARS).

Employee Portal

Every organisation gets a self-service employee portal at /portal/[your-org-slug]. Employees log in with their work email.

Payslips

View and download PDF payslips for all past pay periods.

Leave Requests

Submit annual, sick, and family responsibility leave. Track approval status in real time.

Profile

Update contact details and banking information. All PII is encrypted at rest.

POPIA Data Rights

Download a complete export of personal data, or submit a deletion request (Section 23 of POPIA).

Compliance & Reports

EMP201 Monthly Returns

After each payroll run, VerityPay generates an EMP201-compatible XML file containing PAYE, UIF, and SDL totals for the month. Download from Reports → [run] → EMP201 XML and upload directly to SARS eFiling.

IRP5 Annual Reconciliation

At tax year-end (February), VerityPay generates IRP5 certificates for all employees — including all income codes, deductions, and employer contributions for the year. Export as XML for SARS e@syFile™ submission (Growth plan and above).

Bank EFT Files

VerityPay generates salary payment CSV files in the native formats of the four major South African banks:

ABSA
FNB
Nedbank
Standard Bank

Download the EFT file from any completed payroll run and upload it directly to your business banking portal. No manual re-entry of employee banking details required.

Integrations

Xero

Connect VerityPay to your Xero account via Settings → Integrations. Once connected, payroll journals are automatically pushed to Xero after each approved run — debit wages expense, credit payables — saving manual double-entry. The integration uses OAuth 2.0 and respects your Xero chart of accounts.

CSV Employee Import

Available on the Growth plan and above. Download the VerityPay employee CSV template from Employees → Import, fill in your employee data, and upload. The importer validates SA ID numbers, bank account details, and required fields before saving. Errors are shown per row — no partial imports.

Email & SMS Notifications

Payslip notifications are sent automatically to employees by email (Resend) and SMS (Africa's Talking) after a run is approved. Notification preferences are configurable per organisation in Settings → Notifications.

Developer API

VerityPay exposes a REST API for programmatic access. All endpoints are organisation-scoped and require a valid API key.

Authentication

All API requests require a Bearer token in the Authorization header. Generate your API key in Settings → Integrations.

Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

Base URL

https://app.veritypay.co.za/api/v1

Endpoints

GET/:orgSlug/irp5

Returns IRP5 data for all employees in the organisation for the specified tax year.

Query Parameters

yearTax year (e.g. 2025). Defaults to current year.

Example Request

curl -X GET \
  "https://app.veritypay.co.za/api/v1/acme-corp/irp5?year=2025" \
  -H "Authorization: Bearer YOUR_API_KEY"
POST/:orgSlug/invitations

Invite a new admin or payroll user to the organisation. An email is sent to the provided address with a secure invitation link.

Request Body

{
  "email": "jane@acme.co.za",
  "role": "payroll_admin"   // "owner" | "payroll_admin"
}

Example Request

curl -X POST \
  "https://app.veritypay.co.za/api/v1/acme-corp/invitations" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"jane@acme.co.za","role":"payroll_admin"}'

Rate Limits

The API is rate-limited to 100 requests per minute per API key. Exceeding this returns a 429 Too Many Requests response. Use the Retry-After header value to determine when to retry.

JavaScript / TypeScript SDK

A fully typed SDK is available for Node.js and browser environments:

npm install @veritypay/sdk
import { VerityPayClient } from '@veritypay/sdk'

const client = new VerityPayClient({
  apiKey: process.env.VERITYPAY_API_KEY,
  orgSlug: 'acme-corp',
})

// Fetch IRP5 data for 2025
const irp5 = await client.irp5.list({ year: 2025 })

// Invite a payroll admin
await client.invitations.create({
  email: 'jane@acme.co.za',
  role: 'payroll_admin',
})

Webhook Events

VerityPay can POST event notifications to your endpoint when key events occur. Configure your webhook URL in Settings → Integrations.

EventTriggered When
payroll.run.approvedA payroll run is approved and locked
payroll.run.exportedEFT or EMP201 file is downloaded
employee.createdNew employee record is saved
employee.terminatedEmployee is marked as terminated
leave.approvedLeave request is approved by admin

Security & POPIA

Data Encryption

All personally identifiable information — SA ID numbers, bank account numbers, passport numbers — is encrypted with AES-256 at the application layer before being written to the database. Database administrators cannot read raw PII values.

Role-Based Access Control

Owner

Full access including billing, user management, and organisation settings.

Payroll Admin

Manage employees, run payroll, and access reports. Cannot change billing or delete the organisation.

Employee

Access to own payslips, leave requests, and profile via the Employee Portal only.

POPIA Compliance

  • Employees can download a full export of their personal data from the portal
  • Employees can submit a POPIA deletion request (Section 23)
  • Data is retained only as long as required by SARS obligations (5 years)
  • No data is sold or shared with third parties beyond the processors listed in our Privacy Policy
  • All data is hosted in South Africa

Reporting a Vulnerability

If you discover a security vulnerability in VerityPay, please disclose it responsibly by emailing security@veritypay.co.za. Do not create a public GitHub issue for security findings. We will respond within 48 hours.