Programmable
payroll.
A JSON API for South African payroll. Run a cycle, pull payslips, and generate a bank-ready file with a handful of HTTP calls. No SOAP, no SDK lock-in, no ceremony.
- REST + JSON
- OpenAPI 3.1 spec
- Signed webhooks
- 99.95% uptime
curl https://api.payloop.co.za/v1/payroll-runs \ -u "sk_live_pl_a37x9z2…:" \ -H "Idempotency-Key: 2026-10-monthly" \ -d period=2026-10 \ -d frequency=monthly # → 200 OK{ "id": "pr_01J9C2A8...", "period": "2026-10", "status": "compiling", "employee_count": 42, "totals": null, "created_at": "2026-10-25T08:14:11Z"}
Built like an API ought to be.
Predictable resources, sensible defaults, and the four things developers actually want.
Idempotent by default
Every mutating endpoint accepts an Idempotency-Key header. Replays are cheap; double-processing is impossible.
SARS-current tax engine
Calculations use the live 2026/27 brackets, rebates, MTC, UIF cap and SDL threshold — updated within hours of a SARS gazette.
Bank-format exports
FNB, Standard Bank, Capitec, Nedbank, Absa and Investec — choose a format, the API hands you the file ready to upload.
Signed webhooks
Every webhook is signed with an HMAC-SHA256 over the body and timestamp. Verify in three lines of any language.
Run a whole month in four calls.
Compile, calculate, export, dispatch. Every step returns a JSON resource you can poll or webhook on. Idempotent end to end — re-running an action is always safe.
- 01Create a draft run for the period.
- 02Calculate — engine returns line-by-line totals.
- 03Export for your bank — downloadable signed file URL.
- 04Pull payslip URLs — signed PDFs per employee.
import { Payloop } from "@payloop/sdk"; const pl = new Payloop({ apiKey: process.env.PAYLOOP_KEY! }); // 1. Compileconst run = await pl.payrollRuns.create({ period: "2026-10", frequency: "monthly",}); // 2. Calculateawait pl.payrollRuns.calculate(run.id); // 3. Export to FNBconst file = await pl.payrollRuns.export(run.id, { bank: "fnb" });console.log(file.download_url); // 4. Fetch payslipsconst slips = await pl.payrollRuns.payslips(run.id);for (const p of slips) console.log(p.employee_name, p.url);
Real-time, signed.
Every event payloop produces — run created, calculation complete, export ready, payslip sent — is delivered to your endpoint with an HMAC-SHA256 signature over the body and a timestamp. Reject anything that doesn’t verify; the signature scheme is the same as Stripe and GitHub.
payroll_run.calculatedpayroll_run.exportedpayslip.dispatchedemp201.staged
import { createHmac, timingSafeEqual } from "node:crypto"; export function verifyPayloopSignature( body: string, signature: string, // header: payloop-signature secret: string,) { const [t, sig] = signature .split(",") .map((p) => p.split("=")[1]); const expected = createHmac("sha256", secret) .update(`${t}.${body}`) .digest("hex"); return timingSafeEqual( Buffer.from(sig, "hex"), Buffer.from(expected, "hex"), );}
Ship payroll,
programmatically.
Grab a sandbox key in 30 seconds. No credit card. Live keys when you’re ready to push your first run.