The reports endpoints give you aggregated analytics about your revenue, expenses, outstanding invoices, and team performance. All amounts are integers in the smallest currency unit (cents). Every report that totals money returns per-currency breakdowns (an object keyed by ISO 4217 code) rather than a single blind cross-currency number, since an account can bill in more than one currency.
Revenue report
GET /report/revenue
Returns revenue from issued invoices (sent, paid, or paid_partial - not just paid) within a date range, broken down by period.
| Query parameter | Required | Description |
|---|---|---|
| from | Yes | Start date (YYYY-MM-DD or full ISO 8601 timestamp) |
| to | Yes | End date; the whole day is included |
| period | No | Grouping: monthly (default), quarterly, or yearly |
| include_invoices | No | Set to true to include the underlying invoice list, sorted by date descending |
| label | No | Keep only invoices (or payments on a cash basis) of clients carrying at least one of these client labels; repeat or comma-separate. Rows then carry client_labels. |
curl "https://api.rebill.co.za/report/revenue?from=2026-01-01&to=2026-03-31&period=monthly" \ -H "Authorization: Bearer sk_your_secret_key"
Response:
{
"invoice_count": 9,
"revenue_by_currency": { "ZAR": 450000 },
"period_breakdown": [
{
"period": "2026-01",
"label": "Jan 2026",
"count": 3,
"amounts": { "ZAR": 150000 }
}
]
}| Response field | Type | Description |
|---|---|---|
| invoice_count | integer | Number of issued invoices in range |
| revenue_by_currency | object | Total revenue per currency code |
| period_breakdown | array | Per-period rows: period, label, count, amounts (per currency) |
| invoices | array | Individual invoices, only when include_invoices=true |
Outstanding (aging) report
GET /report/outstanding
Returns outstanding invoice balances grouped into aging buckets, measured from each invoice's due date: current (0-30 days), 31-60 days, 61-90 days, and 90+ days overdue. No date range - covers every outstanding invoice regardless of issue date.
| Query parameter | Required | Description |
|---|---|---|
| include_invoices | No | Set to true to include the underlying invoice list, sorted by days overdue descending |
| label | No | Keep only invoices of clients carrying at least one of these client labels; repeat or comma-separate. Rows then carry client_labels. |
curl https://api.rebill.co.za/report/outstanding \ -H "Authorization: Bearer sk_your_secret_key"
Response:
{
"invoice_count": 6,
"outstanding_by_currency": { "ZAR": 320000 },
"aging_breakdown": [
{ "bucket": "current", "label": "Current (0-30 days)", "count": 3, "amounts": { "ZAR": 150000 } },
{ "bucket": "30_days", "label": "31-60 days", "count": 2, "amounts": { "ZAR": 80000 } },
{ "bucket": "60_days", "label": "61-90 days", "count": 1, "amounts": { "ZAR": 60000 } },
{ "bucket": "90_plus", "label": "90+ days overdue", "count": 0, "amounts": {} }
]
}Payments report
GET /report/payments
Returns the payments received in a date range, one row per invoice the payment settled, for reconciling a bank statement. A payment that settled two invoices returns two rows; amount is the part applied to that invoice and payment_amount the full deposit. Any unallocated remainder is its own row with no invoice_id. Rows are sorted by received ascending. Credit adjustments are excluded.
| Query parameter | Required | Description |
|---|---|---|
| from | Yes | Start date (YYYY-MM-DD or full ISO 8601 timestamp), matched on the payment received date |
| to | Yes | End date; the whole day is included |
| client_id | No | Only payments from this client |
| method | No | Only payments with this reconciliation method: eft, cash, card, other, or a gateway such as yoco or paystack |
curl "https://api.rebill.co.za/report/payments?from=2026-09-01&to=2026-09-30" \ -H "Authorization: Bearer sk_your_secret_key"
Response:
{
"payment_count": 2,
"total_by_currency": { "ZAR": 283215 },
"method_breakdown": [
{ "method": "eft", "count": 1, "amounts": { "ZAR": 188715 } },
{ "method": "yoco", "count": 1, "amounts": { "ZAR": 94500 } }
],
"rows": [
{
"payment_id": "pay_abc123",
"received": "2026-09-01T00:00:00Z",
"invoice_id": "inv_xyz789",
"invoice_number": "INV-26860",
"client_id": "cli_def456",
"client_name": "Hayli Soal",
"amount": 94500,
"payment_amount": 94500,
"currency": "ZAR",
"gateway": "yoco",
"method": "yoco",
"channel": "card",
"reference": "EB02.09"
},
{
"payment_id": "pay_ghi789",
"received": "2026-09-01T00:00:00Z",
"invoice_id": "inv_jkl012",
"invoice_number": "INV-26866",
"client_id": "cli_mno345",
"client_name": "Rissa Parker",
"amount": 188715,
"payment_amount": 188715,
"currency": "ZAR",
"gateway": "manual",
"method": "eft",
"reference": "AM01.09.1",
"recorded_by": "[email protected]"
}
]
}| Response field | Type | Description |
|---|---|---|
| payment_count | integer | Number of payments in range (not rows) |
| total_by_currency | object | Total received per currency code, in minor units |
| method_breakdown | array | Per-method rows: method, count (payments), amounts (per currency) |
| rows | array | One row per settled invoice or unallocated remainder, oldest first |
| rows[].gateway | string | Raw source: manual, bank_import, or the gateway name |
| rows[].method | string | Reconciliation bucket: the capture method for manual payments, eft for bank-import matches, the gateway name otherwise |
| rows[].channel | string | The gateway's own channel (card, eft) when known; absent for manual payments |
| rows[].recorded_by | string | Email of the team member who captured a manual payment; absent otherwise |
Client revenue report
GET /report/clients
Returns revenue from issued invoices aggregated per client, sorted by total revenue descending.
| Query parameter | Required | Description |
|---|---|---|
| from | Yes | Start date (YYYY-MM-DD or full ISO 8601 timestamp) |
| to | Yes | End date; the whole day is included |
| include_invoices | No | Set to true to include the underlying invoice list |
| label | No | Keep only clients carrying at least one of these client labels; repeat or comma-separate. Each client row carries client_labels. |
curl "https://api.rebill.co.za/report/clients?from=2026-01-01&to=2026-03-31" \ -H "Authorization: Bearer sk_your_secret_key"
Response:
{
"client_count": 4,
"revenue_by_currency": { "ZAR": 450000 },
"clients": [
{
"client_id": "xyz789",
"client_name": "Acme Corp",
"invoice_count": 5,
"revenue_by_currency": { "ZAR": 250000 },
"invoice_count_by_currency": { "ZAR": 5 },
"average_invoice_by_currency": { "ZAR": 50000 }
}
]
}Expense report
GET /report/expenses
Returns expense totals broken down by category and by period, with an optional profit summary comparing expenses against invoiced revenue.
| Query parameter | Required | Type | Description |
|---|---|---|---|
| from | Yes | date | Start of range (YYYY-MM-DD) |
| to | Yes | date | End of range; the whole day is included |
| period | No | string | monthly (default), quarterly, or yearly |
| include_profit | No | boolean | Include a profit summary comparing revenue against expenses |
curl "https://api.rebill.co.za/report/expenses?from=2026-01-01&to=2026-03-31&period=monthly&include_profit=true" \ -H "Authorization: Bearer sk_your_secret_key"
Response:
{
"total_expenses_by_currency": { "ZAR": 185000 },
"expense_count": 12,
"by_category": [
{ "category_id": "cat-001", "category_name": "Travel & Transport", "count": 5, "totals": { "ZAR": 75000 } }
],
"period_breakdown": [
{ "period": "2026-01", "label": "Jan 2026", "count": 4, "totals": { "ZAR": 62000 } }
],
"profit_summary": {
"revenue_by_currency": { "ZAR": 450000 },
"expenses_by_currency": { "ZAR": 185000 },
"net_profit_by_currency": { "ZAR": 265000 }
}
}The profit_summary field is only present when include_profit=true. Its revenue figure is calculated from invoices issued within the same date range.
Profit and loss report
GET /report/profit-loss
Returns income, expenses, and net profit for a date range, with a per-period breakdown.
| Query parameter | Required | Type | Description |
|---|---|---|---|
| from | Yes | date | Start of range (YYYY-MM-DD) |
| to | Yes | date | End of range; the whole day is included |
| period | No | string | monthly (default), quarterly, or yearly |
| basis | No | string | cash (default) recognises income on the date payment was received; accrual recognises it on invoice_date regardless of payment status |
curl "https://api.rebill.co.za/report/profit-loss?from=2026-01-01&to=2026-03-31&basis=accrual" \ -H "Authorization: Bearer sk_your_secret_key"
Response:
{
"basis": "accrual",
"income_by_currency": { "ZAR": 450000 },
"expenses_by_currency": { "ZAR": 185000 },
"net_by_currency": { "ZAR": 265000 },
"period_breakdown": [
{
"period": "2026-01",
"label": "Jan 2026",
"income_by_currency": { "ZAR": 150000 },
"expenses_by_currency": { "ZAR": 62000 },
"net_by_currency": { "ZAR": 88000 }
}
]
}Adjustments (credit notes, manual corrections) are excluded from cash basis income - only actual payment receipts count.
Summary report
GET /report/summary
Returns combined revenue and expense detail for a date range: every issued invoice and every expense in the window, with totals and net profit. Useful for a single-request dashboard view.
| Query parameter | Required | Description |
|---|---|---|
| from | Yes | Start date (YYYY-MM-DD) |
| to | Yes | End date; the whole day is included |
curl "https://api.rebill.co.za/report/summary?from=2026-01-01&to=2026-03-31" \ -H "Authorization: Bearer sk_your_secret_key"
Response:
{
"invoice_count": 9,
"expense_count": 12,
"revenue_by_currency": { "ZAR": 450000 },
"total_expenses_by_currency": { "ZAR": 185000 },
"net_profit_by_currency": { "ZAR": 265000 },
"invoices": [
{
"id": "abc123",
"number": "INV0001",
"client_name": "Acme Corp",
"invoice_date": "2026-03-01T00:00:00Z",
"due_date": "2026-03-15T00:00:00Z",
"amount": 150000,
"status": "paid",
"currency": "ZAR"
}
],
"expenses": [
{
"id": "exp-001",
"date": "2026-03-10T00:00:00Z",
"supplier_name": "BP Garage Stellenbosch",
"category_name": "Travel & Transport",
"amount": 45000,
"tax_amount": 6522,
"currency": "ZAR"
}
]
}VAT report
GET /report/vat
Returns a VAT return for a date range: output tax on sales minus input (deductible) tax on expenses, split by VAT type. Requires the account to have a VAT number set; returns 403 Forbidden otherwise. Only documents in your account's default currency are counted - foreign-currency invoices and expenses are excluded and their count reported separately.
| Query parameter | Required | Type | Description |
|---|---|---|---|
| from | Yes | date | Start of range (YYYY-MM-DD) |
| to | Yes | date | End of range; the whole day is included |
| basis | No | string | accrual or cash; defaults to your account's VAT basis setting |
curl "https://api.rebill.co.za/report/vat?from=2026-01-01&to=2026-03-31&basis=accrual" \ -H "Authorization: Bearer sk_your_secret_key"
Response:
{
"period": { "from": "2026-01-01", "to": "2026-03-31", "basis": "accrual" },
"currency": "ZAR",
"output": {
"standard_excl": 300000,
"standard_vat": 45000,
"zero_rated_excl": 0,
"exempt_excl": 0,
"total_vat": 45000
},
"input": {
"deductible_net": 38478,
"total_vat": 6522
},
"net_vat": 38478,
"excluded_foreign_count": 0,
"lines": [
{
"type": "sale",
"date": "2026-03-01",
"ref": "INV0001",
"party": "Acme Corp",
"tax_type": "standard",
"net": 300000,
"vat": 45000
}
]
}lines contains one row per invoice (type sale) and per deductible expense (type purchase), for a full audit trail behind the totals.
Tax set-aside report
GET /report/tax-setaside
Estimates income tax to set aside each month based on year-to-date profit, projected annualised. ZA accounts with a ZAR base currency only. Requires an active premium subscription and your account's tax entity type to be set (individual · company · company_sbc) - returns 403 Forbidden with not_available or tax_entity_type_not_set otherwise, and 402 Payment Required on the free plan. Income is recognised on an accrual basis (issued invoices, excluding VAT for VAT-registered accounts) to match how SARS assesses trading income.
| Query parameter | Required | Description |
|---|---|---|
| year | No | A specific SARS tax year label (e.g. 2026); defaults to the tax year containing today |
curl "https://api.rebill.co.za/report/tax-setaside?year=2026" \ -H "Authorization: Bearer sk_your_secret_key"
Response:
{
"entity_type": "individual",
"tax_year_label": 2026,
"from": "2025-03-01",
"to": "2026-02-28",
"current": true,
"months_elapsed": 6,
"currency": "ZAR",
"months": [
{ "period": "2025-03", "label": "Mar 2025", "revenue": 80000, "expenses": 20000, "profit": 60000, "cumulative_profit": 60000 }
],
"ytd_profit": 360000,
"projected_profit": 720000,
"estimated_tax": 90000,
"monthly_set_aside": 7500,
"should_have_by_now": 45000,
"next_provisional_due": "2025-08-31",
"excluded_foreign_count": 0
}Team performance report
GET /report/team
Returns per-team-member quote win/loss and invoice outstanding/paid figures for a date range. Requires an admin-role user; every account has at least one admin (the original account owner), and API-key requests authenticate as that admin automatically, so this endpoint works with a plain API key the same as any other report.
| Query parameter | Required | Description |
|---|---|---|
| from | Yes | Start date (YYYY-MM-DD) |
| to | Yes | End date; the whole day is included |
curl "https://api.rebill.co.za/report/team?from=2026-01-01&to=2026-03-31" \ -H "Authorization: Bearer sk_your_secret_key"
Response:
{
"rows": [
{
"owner_user_id": "usr_001",
"email": "[email protected]",
"quotes_won_count": 4,
"quotes_won_value_by_currency": { "ZAR": 300000 },
"quotes_lost_count": 1,
"quotes_lost_value_by_currency": { "ZAR": 50000 },
"quotes_pending_count": 2,
"quotes_pending_value_by_currency": { "ZAR": 120000 },
"win_rate": 0.8,
"invoices_outstanding_count": 3,
"invoices_outstanding_by_currency": { "ZAR": 90000 },
"invoices_paid_count": 5,
"invoices_paid_by_currency": { "ZAR": 250000 }
}
]
}Quotes are filtered by quote_date within range; invoices_paid is filtered by invoice_date within range; invoices_outstanding is point-in-time (not date-filtered - it reflects what's outstanding right now). Documents with no owner are grouped under owner_user_id: "" with email: "Unassigned".