Reports
Aggregated reports in JSON, CSV, or XLSX. Six report types covering payouts, funding, fees, cashflow, bank statements, and failed payouts.
All reports support ?format=json|csv|xlsx:
json(default) returns the standard list envelope (object: 'list',data: [...],has_more) for programmatic consumptioncsvreturnstext/csv; charset=utf-8with a filename attachment headerxlsxreturns a properly-formatted Excel workbook with frozen header row + column widths
Common params
Every report accepts:
| Param | Notes |
|---|---|
from | YYYY-MM-DD start date in your merchant timezone (default: today − 29 days) |
to | YYYY-MM-DD end date (default: today) |
currency | Filter to one currency (e.g. NGN). Most reports support; bank-statement requires it for accurate running balance. |
format | json | csv | xlsx |
Date range is interpreted in your merchant’s configured timezone (set on Merchant.timezone, default Africa/Lagos for NG merchants).
Discover available reports
GET /v1/reports
Returns the list of report types this API supports along with their endpoints + supported formats. Useful as a runtime catalog for tooling.
curl https://api.swappr.me/v1/reports \
-H "Authorization: Bearer sk_test_..."{
"object": "list",
"data": [
{
"object": "report_type",
"id": "payouts",
"endpoint": "/v1/reports/payouts",
"formats": ["json", "csv", "xlsx"],
"description": "Daily payout aggregates: paid count, failed count, in-flight count, paid + failed volume."
},
...
]
}Payouts report
GET /v1/reports/payouts
Daily-bucketed payout aggregates per (day, currency).
Response (JSON)
{
"object": "report",
"report_type": "payouts",
"range": { "from": "2026-04-06", "to": "2026-05-05", "timezone": "Africa/Lagos" },
"data": [
{
"day": "2026-05-05",
"currency": "NGN",
"paid_count": 142,
"failed_count": 3,
"in_flight_count": 8,
"paid_amount_minor": "12500000",
"failed_amount_minor": "350000"
},
...
]
}Funding report
GET /v1/reports/funding
Daily-bucketed inflow aggregates by source. Excludes payout reversals (those are refunds, not new inflow) and FX conversion legs (internal, not external).
Sources counted
virtual_account_credit— VA inflows (the main source)admin_credit— Admin top-upspromotional_credit— Promotional creditsreconciliation_adjust— Reconciliation adjustmentsdemo_seed— Sandbox seeddemo_self_fund— Sandbox self-fund
Response (JSON)
{
"object": "report",
"report_type": "funding",
"range": { ... },
"data": [
{
"day": "2026-05-05",
"currency": "NGN",
"source": "virtual_account_credit",
"count": 23,
"amount_minor": "5000000"
},
...
]
}Cashflow report
GET /v1/reports/cashflow
Daily inflow vs outflow netting per currency. Provides the “where’s my cash going?” view.
Response (JSON)
{
"object": "report",
"report_type": "cashflow",
"data": [
{
"day": "2026-05-05",
"currency": "NGN",
"inflow_minor": "5000000",
"outflow_minor": "12500000",
"net_minor": "-7500000",
"inflow_count": 23,
"outflow_count": 142
},
...
]
}Fees report
GET /v1/reports/fees
Daily fee + tax aggregates per (day, currency, applies_to).
applies_to values: payout_single / payout_bulk / payout_reversal / virtual_account_fund.
Response (JSON)
{
"object": "report",
"report_type": "fees",
"data": [
{
"day": "2026-05-05",
"currency": "NGN",
"applies_to": "payout_single",
"count": 142,
"fee_minor": "10650",
"tax_minor": "0"
},
...
]
}Bank statement
GET /v1/reports/bank-statement
Line-by-line ledger statement with running balance — accountant-grade. NOT bucketed; one row per LedgerEntry. Use ?currency= to scope to one wallet (mixing currencies in one statement makes the running balance meaningless).
Response (JSON)
{
"object": "report",
"report_type": "bank_statement",
"currency": "NGN",
"opening_balance_minor": "1000000000",
"closing_balance_minor": "987500000",
"data": [
{
"id": "ckledger_xxx",
"timestamp": "2026-05-05T12:34:56Z",
"source": "payout_debit",
"source_label": "Payout",
"direction": "debit",
"amount_minor": "500000",
"balance_after_minor": "999500000",
"description": "Paid ADAEZE BLESSING NWAFOR",
"source_ref_type": "Payout",
"source_ref_id": "ckpayout_xxx"
},
...
]
}CSV/XLSX variants include OPENING BALANCE and CLOSING BALANCE pseudo-rows so the file is hand-off-able to an accountant.
Failed payouts
GET /v1/reports/failed
Recent failed payouts list (NOT aggregated). Each row has the failure code + message + auto-reversal flag.
JSON response capped at 500 rows; CSV/XLSX exports up to 5000 rows.
Response (JSON)
{
"object": "report",
"report_type": "failed_payouts",
"count": 47,
"data": [
{
"id": "ckpayout_xxx",
"reference": "po_xxx",
"currency": "NGN",
"amount_minor": "500000",
"recipient_name": "JOHN DOE",
"recipient_account": "0123456789",
"recipient_bank_code": "058",
"failure_code": "INSUFFICIENT_FUNDS",
"failure_message": "Recipient account closed",
"auto_reversed": true,
"created_at": "2026-05-05T12:34:56Z",
"completed_at": "2026-05-05T12:35:01Z"
},
...
]
}CSV / XLSX format
Both formats use the same column set; rendered as text in CSV, properly typed cells in XLSX.
Example: download payouts report as XLSX
curl "https://api.swappr.me/v1/reports/payouts?from=2026-04-01&to=2026-04-30&format=xlsx" \
-H "Authorization: Bearer sk_test_..." \
-o payouts-april-2026.xlsxThe Content-Disposition header includes a sensible default filename like payouts-2026-04-01-2026-04-30.xlsx.
Money formatting: JSON returns minor units as strings (BigInt-safe). CSV/XLSX renders amounts in major units (numbers, e.g. 12500.00 for ₦12,500.00) so the file is accountant-friendly.