View as Markdown

Metrics & Reports API

Instead of pulling raw orders and computing KPIs yourself, OmniCart can compute them for you: revenue, order counts, AOV, refunds, retention, channel breakdowns, and top products — consistent with what the admin dashboard shows.

Prerequisite: an admin token — see Data Access Overview.


1. Dashboard metrics — GET /admin/metrics#

One call returns the full KPI snapshot for a date range.

curl -G 'https://your-store.omnicart.cc/admin/metrics' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  --data-urlencode 'startDate=2026-07-01T00:00:00Z' \
  --data-urlencode 'endDate=2026-07-14T23:59:59Z' \
  --data-urlencode 'comparison=none'

Query parameters:

Param Default Notes
startDate / endDate last 30 days ISO timestamps recommended. Max range: 365 days.
comparison previous previous (prior period), year_ago, or none. Use none for scheduled pulls unless you want change percentages.
salesChannel all Scope to one store/channel by ID.

Response structure (abridged):

{
  "success": true,
  "metrics": {
    "summary": {
      "cards": [
        { "id": "total_revenue", "title": "Total Revenue", "value": 48210.55, "format": "currency", "changePercentage": 12.4, "trend": "up" },
        { "id": "total_orders", "title": "Total Orders", "value": 1284, "format": "number" }
      ]
    },
    "trends": [ "..." ],
    "breakdowns": {
      "salesChannels": [ { "channelId": "...", "channelName": "...", "orders": 512, "revenue": 19882.12, "averageOrderValue": 38.83 } ],
      "products": [ { "productId": "...", "title": "...", "quantity": 431, "revenue": 12931.69 } ]
    },
    "section_errors": {}
  }
}

Card IDs you can rely on in metrics.summary.cards[]:

id Meaning Format
total_revenue Revenue for the period currency
total_orders Order count number
average_order_value AOV currency
total_refunded / refund_rate / refund_count Refund figures currency / % / number
new_customers / returning_customers Customer counts number
customer_retention_rate Returning-customer rate percentage
revenue_per_customer Revenue ÷ unique customers currency
unfulfilled_paid_orders Paid orders not yet fulfilled number

Two things scheduled consumers must handle:

  1. section_errors — partial results return HTTP 200. If one section fails to compute, the response still succeeds and the failing section is listed in section_errors (its data will be missing/null). Always check it before trusting a snapshot.
  2. Freshness: results are cached server-side for up to ~5 minutes. Fine for dashboards; if you reconcile against raw orders, expect small timing differences at the cache boundary.

Rate limit: 60 requests/minute per user where enforced (deployment-dependent — design to the budget and handle 429s, but don't be surprised if you never see one).


2. Batch reports — POST /admin/metrics/batch#

Fetch multiple report types or multiple date ranges in one round trip. The 50-requests-per-batch maximum is always enforced; the 5-batches/minute rate limit applies where rate limiting is enabled in your deployment.

curl -X POST 'https://your-store.omnicart.cc/admin/metrics/batch' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "requests": [
      {
        "id": "revenue-last-7d",
        "type": "dashboard",
        "filters": { "range": { "start": "2026-07-14T00:00:00Z", "end": "2026-07-21T00:00:00Z" }, "comparison": "none" }
      },
      {
        "id": "revenue-last-30d",
        "type": "dashboard",
        "filters": { "range": { "start": "2026-06-21T00:00:00Z", "end": "2026-07-21T00:00:00Z" }, "comparison": "none" }
      }
    ]
  }'

Each request has a caller-chosen id (echoed back), a typedashboard, paid_acquisition, order_report, or fulfillment_report — and type-specific filters. The response returns per-request results plus a summary:

{
  "results": [
    { "id": "revenue-last-7d", "success": true, "data": { "..." : "..." }, "cacheHit": true, "executionTimeMs": 12 }
  ],
  "summary": { "total": 2, "successful": 2, "failed": 0, "cacheHitRate": 50 }
}

Check success per item — one failed request does not fail the batch.


3. Custom metric definitions — /admin/metrics-registry#

The registry holds named metric formulas (system-provided and your own), e.g. net_revenue = SUM({order_total}) - SUM({refund_total}).

Discover available metrics and their IDs:

curl -G 'https://your-store.omnicart.cc/admin/metrics-registry/definitions' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  --data-urlencode 'category=revenue'

Returns { "metrics": [...], "count": n } — each definition has an id, name (e.g. total_revenue, net_revenue, average_order_value, completed_orders), category, and formula. Browse available formula building blocks with GET /admin/metrics-registry/placeholders.

Execute a formula:

curl -X POST 'https://your-store.omnicart.cc/admin/metrics-registry/execute' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{ "metric_id": "metdef_01...", "context": { "order_total": [19.99, 45.50], "refund_total": [19.99] } }'

Two important notes:

  • metric_id is the definition's id, not its name — look it up via the definitions endpoint first.
  • execute evaluates the formula against the values you supply in context; it does not query your order history by date range. For date-ranged KPIs, use GET /admin/metrics or the batch endpoint above. The registry is for defining and computing custom formulas over data you've already aggregated.

  1. Once per day (after your business day closes), call GET /admin/metrics with an explicit ISO range for that day and comparison=none.
  2. Extract the cards you need by id (total_revenue, total_orders, average_order_value, total_refunded).
  3. Check section_errors is empty; retry once after a minute if not.
  4. Append the row to your warehouse/spreadsheet — this becomes the fact table your BI tool reads. See Looker & Looker Studio.