Skip to main content
This guide details the steps needed for a business to pay its workers via a scheduled payroll. Cadana handles fund collection, scheduling, and disbursement automatically.

Prerequisites

1

API key from Dashboard

Get your API key from the Cadana Dashboard. See Authentication for details.
2

Compliance-approved business

Your business must have completed KYB verification. See KYB Requirements.
3

Account funded

Your business account must have sufficient funds to cover the payroll. See Fund Your Account.
4

Onboarded workers

Workers must be onboarded as Persons with payment methods configured — you’ll use their personId to set up pay entries. See Onboard Workers.

Step 1: Create a Payroll

Start by creating an empty payroll shell. Specify the worker type and whether this is a one-off or regular payroll.
bash
curl -X POST 'https://api.cadanapay.com/v1/payrolls' \
  -H 'Authorization: Bearer YOUR_API_KEY'
Response:
{
  "payrollId": "a1b2c3d4-e5f6-7890-abcd-ef0123456789"
}
Save the payrollId — you’ll use it in the next steps.

Payroll Types

FieldValuesDescription
workerTypeEMPLOYEE, CONTRACTORType of workers being paid
typeONE_OFF, REGULAROne-off payment or recurring payroll

Step 2: Save Entries

Add the pay date, pay period, and compensation entries for each worker. Each entry requires a personId and salary amount. If you set compensation info (compInfo) when onboarding the worker, you can retrieve it from the Person profile with GET /v1/persons/{personId} and use those values for the salary entry.
bash
curl -X POST 'https://api.cadanapay.com/v1/payrolls/a1b2c3d4-e5f6-7890-abcd-ef0123456789/save' \
  -H 'Authorization: Bearer YOUR_API_KEY'
Returns 204 on success. The payroll status moves to saved. Fetch the payroll with GET /v1/payrolls/{id} to see the calculated debit — the total amount that will be debited from the business account.
Amounts are in the lowest denomination of the currency. For USD, 100000 = $1,000.00. For GHS, 500000 = GHS 5,000.00.
You can re-save a payroll to update entries before approving. Each save replaces the previous entries.
For workers with variable pay (e.g., hourly contractors), set compInfo.salary to 0 during onboarding and provide the actual amount when saving payroll entries.

Custom Metadata

You can pass a tags object on both the create and save requests to store custom metadata against the payroll (e.g., internal reference IDs, department codes). This is a free-form object — any key-value pairs you include will be persisted and returned when you retrieve the payroll.

Custom Fees (Platforms)

Platforms can pass a customFees array on the save request to add platform-specific fee line items to the payroll invoice. Each item requires a name and amount. These are additive — they supplement standard per-seat subscription fees and are included in the total amount collected by Cadana on your behalf.
{
  "customFees": [
    { "name": "Platform Fee", "amount": { "amount": 50000, "currency": "USD" } },
    { "name": "Processing Fee", "amount": { "amount": 10000, "currency": "USD" } }
  ]
}
Custom fee items do not participate in revenue share calculations. Validation returns 400 for empty names, non-positive amounts, or missing currency.

Step 3: Approve

Once you’re satisfied with the entries, approve the payroll. This triggers fund collection and schedules disbursement.
bash
curl -X POST 'https://api.cadanapay.com/v1/payrolls/a1b2c3d4-e5f6-7890-abcd-ef0123456789/approve' \
  -H 'Authorization: Bearer YOUR_API_KEY'
Returns 204 on success. The payroll status moves to approved. After approval:
  • If the business has insufficient funds, the payroll moves to awaiting funds. If a bank account is connected, an ACH debit initiates automatically.
  • If the scheduled date is in the future, the payroll will be processed on the scheduled day.
  • Once funds are available, the payroll processes and disburses payments to workers automatically.

Tracking Payroll Status

Poll the payroll to check its current status and see calculated totals.
bash
curl -X GET 'https://api.cadanapay.com/v1/payrolls/a1b2c3d4-e5f6-7890-abcd-ef0123456789' \
  -H 'Authorization: Bearer YOUR_API_KEY'
Response:
{
  "payrollId": "a1b2c3d4-e5f6-7890-abcd-ef0123456789",
  "workerType": "CONTRACTOR",
  "status": "completed",
  "type": "ONE_OFF",
  "invoiceId": "8dbaa174-b5a0-4396-8c87-77e746b50917",
  "payrollDate": "2026-02-28",
  "numPeople": 2,
  "debit": { "amount": 175000, "currency": "USD" },
  "gross": { "amount": 175000, "currency": "USD" },
  "net": { "amount": 175000, "currency": "USD" },
  "tax": { "amount": 0, "currency": "USD" },
  "pension": { "amount": 0, "currency": "USD" },
  "payPeriod": {
    "fromDate": "2026-02-01",
    "toDate": "2026-02-28"
  },
  "entries": [
    {
      "personId": "8ef9a712-cdae-4110-b1ea-9ba95abbee6e",
      "salary": { "amount": 100000, "currency": "USD" }
    },
    {
      "personId": "3c7d9e21-fa4b-4a12-bc89-0d1234567890",
      "salary": { "amount": 75000, "currency": "USD" }
    }
  ]
}
Once a payroll reaches completed, the response includes an invoiceId. Use GET /v1/invoices/{invoiceId} to retrieve a detailed breakdown of fees charged for the payroll run.

List All Payrolls

bash
curl -X GET 'https://api.cadanapay.com/v1/payrolls' \
  -H 'Authorization: Bearer YOUR_API_KEY'
Response:
{
  "data": [
    {
      "payrollId": "a1b2c3d4-e5f6-7890-abcd-ef0123456789",
      "workerType": "CONTRACTOR",
      "status": "completed",
      "type": "ONE_OFF",
      "payrollDate": "2026-02-28",
      "numPeople": 2,
      "debit": { "amount": 175000, "currency": "USD" },
      "gross": { "amount": 175000, "currency": "USD" },
      "net": { "amount": 175000, "currency": "USD" },
      "tax": { "amount": 0, "currency": "USD" },
      "pension": { "amount": 0, "currency": "USD" },
      "payPeriod": {
        "fromDate": "2026-02-01",
        "toDate": "2026-02-28"
      }
    }
  ]
}

Status Flow

created → saved → approved → scheduled → processing → completed

                awaiting funds
StatusMeaning
createdEmpty payroll shell, no entries yet
savedEntries added, ready for approval
approvedApproved, Cadana is collecting funds
awaiting fundsInsufficient balance — payroll will proceed once funded
scheduledFunds collected, scheduled for the payroll date
processingDisbursements being sent to workers
completedAll disbursements confirmed
For the full lifecycle including webhooks and multi-currency handling, see Payroll Lifecycle.

Webhooks

Subscribe to payroll and transaction events to track progress without polling. Payroll status changes:
JSON
{
  "id": "e13b9e14-c062-42ea-8563-8fc9223b29b5",
  "status": "completed",
  "tenantKey": "cad95193904"
}
Individual transaction events (transaction.initiated, transaction.succeeded, transaction.failed) fire for each worker’s payment. See Webhooks to configure your endpoint and Events for all event types.

Troubleshooting

IssueCauseSolution
401 UnauthorizedInvalid or missing API keyCheck your API key in the Dashboard
400 on saveMissing required fieldsEnsure payrollDate, payPeriod, and at least one entry with personId and salary are provided
Stuck in awaiting fundsInsufficient business account balanceFund your business account, then the payroll will proceed automatically
Payroll won’t approveEntries not savedSave entries (Step 2) before approving

Next Steps