Skip to content

Reports

The reports API returns aggregated analytics for a workspace across four domains: revenue, customers, loyalty points, and passes/campaigns. Every report shares the same query contract — a date range, a bucket granularity, an optional comparison window, and optional filters — and returns a consistent shape made of kpis, a trend time series (with an optional previousBuckets comparison series), a breakdown, a top list, the appliedFilters, and the resolved range.

Auth (all endpoints): Bearer token — caller must be a member of the workspace in the path (createWorkspaceGuard).

Shared query parameters

All four report endpoints accept the same query string, validated by reportQuerySchema:

ParameterTypeRequiredDefaultDescription
fromstring (ISO date)YesStart of the range. Must be a valid ISO date and strictly before to.
tostring (ISO date)YesEnd of the range (inclusive). Must be a valid ISO date and strictly after from.
bucket"day" | "week" | "month"NodayTime-series bucket granularity. Weeks start Monday (UTC).
compare"true" | "false"NotrueWhen true, computes a previous window of equal length immediately before from and returns kpis.*.previous / deltaPct and trend.previousBuckets. When false, those are null.
tier_idstring (UUID)NoRestrict to clients in this tier. Honored by revenue, customers, and loyalty reports.
sourcestring (1–100 chars)NoRestrict to transactions from this source. Honored by the revenue report.
project_idstring (UUID)NoRestrict to passes in this project. Honored by the passes report.

Invalid query parameters (bad dates, from not before to, malformed UUIDs) return a validation error.

Shared response shapes

ReportKpi{ "current": number, "previous": number | null, "deltaPct": number | null }. previous and deltaPct are null when compare=false (and deltaPct is also null when previous is 0).

range{ "from", "to", "bucket", "previousFrom": string | null, "previousTo": string | null }.

appliedFilters — echoes only the filters that were actually applied for that report (e.g. { "tier_id": "..." }).


Revenue Report

GET /wallethero-api/workspace/:workspaceId/reports/revenue

Aggregates transaction revenue: KPIs (total revenue, transaction count, average order value, unique customers), a revenue/transactions trend, a per-source breakdown, and the top spending clients.

Auth: Bearer token — workspace member.

Path Parameters

ParameterTypeDescription
workspaceIdstring (UUID)Workspace identifier

Query Parameters

See shared query parameters. Honors tier_id and source.

Example Request

bash
curl "https://api.wallethero.app/wallethero-api/workspace/WORKSPACE_ID/reports/revenue?from=2026-05-01&to=2026-06-01&bucket=day&compare=true" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response (200)

json
{
  "data": {
    "kpis": {
      "revenue": { "current": 12450.5, "previous": 9800, "deltaPct": 27.04 },
      "transactionCount": { "current": 312, "previous": 270, "deltaPct": 15.56 },
      "aov": { "current": 39.9, "previous": 36.3, "deltaPct": 9.92 },
      "uniqueCustomers": { "current": 188, "previous": 160, "deltaPct": 17.5 }
    },
    "trend": {
      "buckets": [
        { "bucket": "2026-05-01", "revenue": 420.5, "transactions": 11 }
      ],
      "previousBuckets": [
        { "bucket": "2026-04-01", "revenue": 380, "transactions": 9 }
      ]
    },
    "breakdown": [
      { "source": "pos", "revenue": 9200, "transactions": 240 },
      { "source": "unknown", "revenue": 3250.5, "transactions": 72 }
    ],
    "top": [
      {
        "clientId": "CLIENT_ID",
        "name": "Jane Doe",
        "email": "[email protected]",
        "revenue": 980,
        "txCount": 14,
        "aov": 70,
        "lastTransactionAt": "2026-05-28T14:10:00.000Z"
      }
    ],
    "appliedFilters": {},
    "range": {
      "from": "2026-05-01T00:00:00.000Z",
      "to": "2026-06-01T00:00:00.000Z",
      "bucket": "day",
      "previousFrom": "2026-03-31T00:00:00.000Z",
      "previousTo": "2026-05-01T00:00:00.000Z"
    }
  }
}

SDK

typescript
const report = await wh.reports.getRevenueReport(workspaceId, {
  from: "2026-05-01",
  to: "2026-06-01",
  bucket: "day",
  compare: true,
});

Customers Report

GET /wallethero-api/workspace/:workspaceId/reports/customers

Aggregates customer activity: KPIs (new clients, active clients, repeat-purchase rate, returning customers), a signups trend, a per-bucket new-vs-returning buyers split, a per-tier breakdown, and the top clients by transaction count.

Auth: Bearer token — workspace member.

Path Parameters

ParameterTypeDescription
workspaceIdstring (UUID)Workspace identifier

Query Parameters

See shared query parameters. Honors tier_id.

Example Request

bash
curl "https://api.wallethero.app/wallethero-api/workspace/WORKSPACE_ID/reports/customers?from=2026-05-01&to=2026-06-01&bucket=week" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response (200)

json
{
  "data": {
    "kpis": {
      "newClients": { "current": 88, "previous": 72, "deltaPct": 22.22 },
      "activeClients": { "current": 1240, "previous": 1180, "deltaPct": 5.08 },
      "repeatPurchaseRate": { "current": 41.3, "previous": 38.7, "deltaPct": 6.72 },
      "returningCustomers": { "current": 96, "previous": 90, "deltaPct": 6.67 }
    },
    "trend": {
      "buckets": [ { "bucket": "2026-04-27", "signups": 21 } ],
      "previousBuckets": [ { "bucket": "2026-03-30", "signups": 18 } ]
    },
    "buyersSplit": [
      { "bucket": "2026-04-27", "newBuyers": 12, "returningBuyers": 34 }
    ],
    "breakdown": [
      { "tierId": "TIER_ID", "tierName": "Gold", "tierColor": "#d4af37", "clients": 310 }
    ],
    "top": [
      {
        "clientId": "CLIENT_ID",
        "name": "John Smith",
        "email": "[email protected]",
        "revenue": 540,
        "txCount": 22,
        "aov": 24.55,
        "lastTransactionAt": "2026-05-30T09:00:00.000Z"
      }
    ],
    "appliedFilters": {},
    "range": {
      "from": "2026-05-01T00:00:00.000Z",
      "to": "2026-06-01T00:00:00.000Z",
      "bucket": "week",
      "previousFrom": "2026-03-31T00:00:00.000Z",
      "previousTo": "2026-05-01T00:00:00.000Z"
    }
  }
}

SDK

typescript
const report = await wh.reports.getCustomersReport(workspaceId, {
  from: "2026-05-01",
  to: "2026-06-01",
  bucket: "week",
});

Loyalty Report

GET /wallethero-api/workspace/:workspaceId/reports/loyalty

Aggregates loyalty points and reward redemptions: KPIs (points earned, spent, expired, redemption count), an earned/spent points trend, a redemption-status breakdown, and the top redeemed rewards. Spend and expire amounts are reported as positive magnitudes.

Auth: Bearer token — workspace member.

Path Parameters

ParameterTypeDescription
workspaceIdstring (UUID)Workspace identifier

Query Parameters

See shared query parameters. Honors tier_id.

Example Request

bash
curl "https://api.wallethero.app/wallethero-api/workspace/WORKSPACE_ID/reports/loyalty?from=2026-05-01&to=2026-06-01" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response (200)

json
{
  "data": {
    "kpis": {
      "pointsEarned": { "current": 54000, "previous": 48000, "deltaPct": 12.5 },
      "pointsSpent": { "current": 21000, "previous": 19000, "deltaPct": 10.53 },
      "pointsExpired": { "current": 1200, "previous": 1500, "deltaPct": -20 },
      "redemptionCount": { "current": 145, "previous": 130, "deltaPct": 11.54 }
    },
    "trend": {
      "buckets": [ { "bucket": "2026-05-01", "earned": 1800, "spent": 700 } ],
      "previousBuckets": [ { "bucket": "2026-04-01", "earned": 1600, "spent": 600 } ]
    },
    "breakdown": [
      { "status": "fulfilled", "count": 120 },
      { "status": "pending", "count": 25 }
    ],
    "top": [
      {
        "rewardId": "REWARD_ID",
        "name": "Free Coffee",
        "redemptions": 64,
        "pointsSpent": 6400,
        "fulfilledPct": 92.18
      }
    ],
    "appliedFilters": {},
    "range": {
      "from": "2026-05-01T00:00:00.000Z",
      "to": "2026-06-01T00:00:00.000Z",
      "bucket": "day",
      "previousFrom": "2026-03-31T00:00:00.000Z",
      "previousTo": "2026-05-01T00:00:00.000Z"
    }
  }
}

SDK

typescript
const report = await wh.reports.getLoyaltyReport(workspaceId, {
  from: "2026-05-01",
  to: "2026-06-01",
});

Passes Report

GET /wallethero-api/workspace/:workspaceId/reports/passes

Aggregates pass and campaign activity: KPIs (passes created, wallet registrations, campaigns completed, campaign messages processed), a passes/registrations trend, an Apple-vs-Google wallet breakdown, and the top campaigns by processed messages.

Auth: Bearer token — workspace member.

Path Parameters

ParameterTypeDescription
workspaceIdstring (UUID)Workspace identifier

Query Parameters

See shared query parameters. Honors project_id.

Example Request

bash
curl "https://api.wallethero.app/wallethero-api/workspace/WORKSPACE_ID/reports/passes?from=2026-05-01&to=2026-06-01&project_id=PROJECT_ID" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response (200)

json
{
  "data": {
    "kpis": {
      "passesCreated": { "current": 420, "previous": 380, "deltaPct": 10.53 },
      "walletRegistrations": { "current": 510, "previous": 470, "deltaPct": 8.51 },
      "campaignsCompleted": { "current": 6, "previous": 4, "deltaPct": 50 },
      "campaignMessagesProcessed": { "current": 3200, "previous": 2800, "deltaPct": 14.29 }
    },
    "trend": {
      "buckets": [ { "bucket": "2026-05-01", "passes": 18, "registrations": 22 } ],
      "previousBuckets": [ { "bucket": "2026-04-01", "passes": 15, "registrations": 0 } ]
    },
    "breakdown": { "apple": 290, "google": 220 },
    "top": [
      {
        "campaignId": "CAMPAIGN_ID",
        "name": "June Promo",
        "status": "completed",
        "audienceSize": 1200,
        "processed": 1180,
        "failed": 20,
        "completedAt": "2026-05-20T16:00:00.000Z"
      }
    ],
    "appliedFilters": { "project_id": "PROJECT_ID" },
    "range": {
      "from": "2026-05-01T00:00:00.000Z",
      "to": "2026-06-01T00:00:00.000Z",
      "bucket": "day",
      "previousFrom": "2026-03-31T00:00:00.000Z",
      "previousTo": "2026-05-01T00:00:00.000Z"
    }
  }
}

Note: in trend.previousBuckets the registrations value is always 0 — only the current-window registration series is computed.

SDK

typescript
const report = await wh.reports.getPassesReport(workspaceId, {
  from: "2026-05-01",
  to: "2026-06-01",
  project_id: projectId,
});

WalletHero Documentation