OI Payments Docs
Admin dashboard

Reports

LIVE totals by application and day with success rate, plus customer analytics (top spenders, new vs returning, repeat-purchase rate).

Admin reports give you a high-level, LIVE-only view of payment volume, health, and customers across the apps you have scope for. There are two endpoints, both admin-session authenticated and both gated by the report:read authority:

EndpointReturnsPurpose
GET /admin/reports/summaryPaymentReportDtoTotals by app and by day plus the overall success rate
GET /admin/reports/customersCustomerReportDtoTop spenders plus new/returning, repeat and failure figures

Every figure is app-scoped to your grants — exactly like transaction search — so you only see the apps your role is scoped to.

Reports cover LIVE activity only. Test-mode payments are excluded from every figure so the numbers reflect real money — consistent with reconciliation and the modes model. Unlike the windowed dashboard analytics endpoints (which take mode as a required query parameter), reports take no mode parameter — they are always LIVE.

For near-real-time, mode-aware tiles, timeseries and aging breakdowns, use the dashboard analytics endpoints instead. For row-level detail behind these aggregates, use transaction search and its CSV export.

All responses use the standard envelope — { "data": …, "meta": …, "pagination": null }. Both endpoints return a single object (no pagination), so pagination is always null. The examples below show just the data payload after the first one.

Summary report

GET /api/v1/admin/reports/summary returns aggregate totals — by application and by day — together with the overall counts and payment success rate over an optional date window.

Query parameters

FieldTypeRequiredNotes
fromdate (YYYY-MM-DD)NoInclusive start of the window. Omit for no lower bound.
todate (YYYY-MM-DD)NoInclusive end of the window — the whole to day is included. Omit for no upper bound.
curl "http://localhost:8080/api/v1/admin/reports/summary?from=2026-06-01&to=2026-06-30" \
  -H "Authorization: Bearer sess_live_3f9a8b21c47d"
{
  "data": {
    "byApp": [
      { "applicationId": 100, "count": 1240, "succeededCount": 1180, "grossSucceededMinor": 177000000 }
    ],
    "byDay": [
      { "date": "2026-06-29", "count": 64, "succeededCount": 61, "grossSucceededMinor": 9150000 }
    ],
    "totalCount": 1240,
    "succeededCount": 1180,
    "grossSucceededMinor": 177000000,
    "successRate": 0.9516
  },
  "meta": { "success": true, "message": null, "errorCode": null, "timestamp": "2026-06-30T12:00:00Z" },
  "pagination": null
}

grossSucceededMinor is integer minor units (paisa): 177000000 means 1,770,000.00 BDT. See money. successRate is a 0..1 ratio (0.9516 = 95.16%).

PaymentReportDto

FieldTypeNotes
byApparray of AppTotalRowOne row per app in scope.
byDayarray of DayTotalRowOne row per calendar day in the window.
totalCountintegerTotal LIVE payments in the window.
succeededCountintegerHow many of those succeeded.
grossSucceededMinorinteger (paisa)Gross succeeded amount across the window.
successRatenumber (0..1)succeededCount / totalCount; 0 over an empty window.

AppTotalRowapplicationId (integer), count (integer), succeededCount (integer), grossSucceededMinor (integer, paisa).

DayTotalRowdate (YYYY-MM-DD), count (integer), succeededCount (integer), grossSucceededMinor (integer, paisa).

Customer analytics

GET /api/v1/admin/reports/customers ranks your highest-spending customers and summarises how the window's active customers break down into new vs returning, repeat buyers, and customers who hit a failed payment. Like the summary, it is gated by report:read, LIVE-only, and narrowed to your app scope.

Query parameters

FieldTypeRequiredNotes
fromdate (YYYY-MM-DD)NoInclusive start of the window. Omit for no lower bound.
todate (YYYY-MM-DD)NoInclusive end of the window — the whole to day is included. Omit for no upper bound.
limitintegerNoHow many top customers to return. Defaults to 10; values ≤ 0 fall back to 10 and the maximum is clamped to 100.
curl "http://localhost:8080/api/v1/admin/reports/customers?from=2026-06-01&to=2026-06-30&limit=10" \
  -H "Authorization: Bearer sess_live_3f9a8b21c47d"
{
  "data": {
    "topCustomers": [
      {
        "customerRefId": 9001,
        "externalCustomerId": "cust_ext_47Ksample",
        "applicationId": 100,
        "grossSucceededMinor": 4500000,
        "succeededCount": 6
      }
    ],
    "activeCustomers": 312,
    "newCustomers": 118,
    "returningCustomers": 194,
    "repeatPurchaseRate": 0.41,
    "customersWithFailures": 27
  },
  "meta": { "success": true, "message": null, "errorCode": null, "timestamp": "2026-06-30T12:00:00Z" },
  "pagination": null
}

CustomerReportDto

FieldTypeNotes
topCustomersarray of TopCustomerRowHighest-spending customers in the window, ranked by grossSucceededMinor; at most limit rows.
activeCustomersintegerCustomers with at least one succeeded LIVE payment in the window.
newCustomersintegerActive customers whose first-ever succeeded purchase falls in the window (activeCustomers − returningCustomers).
returningCustomersintegerActive customers who also had a succeeded payment before the window opened.
repeatPurchaseRatenumber (0..1)Share of active customers with ≥ 2 succeeded payments in the window; 0 over an empty window.
customersWithFailuresintegerCustomers who saw at least one failed payment in the window.

TopCustomerRowcustomerRefId (integer, the internal customer reference id), externalCustomerId (string, the app's own customer id), applicationId (integer, owning app), grossSucceededMinor (integer, paisa — total succeeded spend in the window), succeededCount (integer — succeeded payments in the window).

How customers are classified

The window's active customers are derived from the succeeded LIVE payment stream: active = at least one succeeded payment in the window; returning = active and had a succeeded payment before the window opened; new = active minus returning; a repeat buyer is an active customer with two or more succeeded payments in the window.

Customers are identified per app by their externalCustomerId. Because every record carries app_id and the report is app-scoped, one app never sees another app's customers — see app isolation and customers.

On this page