Information
- OpenAPI version:
3.1.0
The REST API for systems integrating with Payloom: HRIS, accounting, data warehouses, and platforms that offer payroll to their own customers.
The key is the tenant. An organization’s key identifies both the caller and the organization, so its requests never name an organization (a header is ignored).
Money is always an object: {"amount_minor": 50000, "currency": "GHS"}.
amount_minor is an integer in the currency’s minor unit (pesewas, cents,
kobo). Zero-decimal currencies such as XOF have a 1:1 minor unit. Payloom
never sends floats and never sums across currencies.
Lists are cursor-paginated. Pass the previous response’s next_cursor as
starting_after; cursors stay valid while rows are inserted, which offsets do
not. Use updated_since to sync incrementally between webhook deliveries.
Retries. Send an Idempotency-Key header on every POST and PATCH. A retry
with the same key and body returns the original response (with
Idempotent-Replay: true) instead of acting twice, which matters because a
429 explicitly invites you to retry. Reusing a key for a different body is
refused. Keys are remembered for 24 hours.
Where Payloom is not available. A request from a country Payloom does not
serve is refused with 451 and the code region_unavailable. Retrying does
not help.
A key feeds and reads; people decide. A key reads what its scopes cover and submits inputs a person later acts on (employees, pay, one-off earnings, leave requests). It never makes a decision a person is accountable for (approving, reopening or paying a run, choosing the bank account): those stay in the console.
Rather than polling, register an endpoint in the Payloom console and we POST
events to it as they happen. Every event is listed under webhooks below,
with the resource it carries. payslip.published fires once per payslip
when its pay run is marked paid; leave.requested and leave.decided fire
when a request is submitted and when it is approved or declined.
Each request carries:
Payloom-Signature: t=1753440000,v1=<hex hmac>
Payloom-Event-Id: evt_9f2c...
Payloom-Event-Type: pay_run.approved
Payloom-Delivery-Id: ...
Payloom-Attempt: 1
Verify every request. Compute
HMAC-SHA256(your_signing_secret, "<t>.<raw request body>") and compare it in
constant time to a v1 value. Reject anything where t is more than five
minutes old. The timestamp is inside the signed string precisely so a
captured request cannot be replayed later. During a secret rotation the
header carries several v1 values; a match against any one is valid, which
is what lets you roll a secret without dropping deliveries.
The body is an envelope:
{
"id": "evt_9f2c...", "type": "pay_run.approved",
"api_version": "2026-07-25", "created_at": "2026-07-25T10:00:00Z",
"organization_id": "...", "livemode": true,
"data": { "object": { ... } }
}
data.object is the same representation this API returns for that resource,
frozen at the moment the event occurred: a replay resends the original bytes,
not the resource’s current state.
Respond 2xx quickly and do the work asynchronously. Anything else is retried
eight times over roughly 24 hours (30s, 2m, 10m, 1h, 3h, 6h, 12h, with
jitter); 410 Gone stops delivery immediately, and twenty consecutive
failures disables the endpoint. Redirects are not followed. Deliveries can be
inspected and replayed from the console.
Events can arrive more than once (a retry after your 2xx was lost) and
are not ordered. Use Payloom-Event-Id to deduplicate.
Authorization: Bearer plm_live_<id>_<secret>. An organization’s keys
are minted in the Payloom console by a member holding
integrations.manage, and carry a subset of that member’s own
permissions. A partner’s keys are minted by Payloom. The secret is shown
once.
Keys are server-side credentials: never ship one in a browser or mobile client. They are rejected on the GraphQL endpoint by design.
Security scheme type: http