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 consumption
  • csv returns text/csv; charset=utf-8 with a filename attachment header
  • xlsx returns a properly-formatted Excel workbook with frozen header row + column widths

Common params

Every report accepts:

ParamNotes
fromYYYY-MM-DD start date in your merchant timezone (default: today − 29 days)
toYYYY-MM-DD end date (default: today)
currencyFilter to one currency (e.g. NGN). Most reports support; bank-statement requires it for accurate running balance.
formatjson | 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-ups
  • promotional_credit — Promotional credits
  • reconciliation_adjust — Reconciliation adjustments
  • demo_seed — Sandbox seed
  • demo_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.xlsx

The 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.