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:
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
from | string (ISO date) | Yes | — | Start of the range. Must be a valid ISO date and strictly before to. |
to | string (ISO date) | Yes | — | End of the range (inclusive). Must be a valid ISO date and strictly after from. |
bucket | "day" | "week" | "month" | No | day | Time-series bucket granularity. Weeks start Monday (UTC). |
compare | "true" | "false" | No | true | When 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_id | string (UUID) | No | — | Restrict to clients in this tier. Honored by revenue, customers, and loyalty reports. |
source | string (1–100 chars) | No | — | Restrict to transactions from this source. Honored by the revenue report. |
project_id | string (UUID) | No | — | Restrict 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
| Parameter | Type | Description |
|---|---|---|
workspaceId | string (UUID) | Workspace identifier |
Query Parameters
See shared query parameters. Honors tier_id and source.
Example Request
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)
{
"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
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
| Parameter | Type | Description |
|---|---|---|
workspaceId | string (UUID) | Workspace identifier |
Query Parameters
See shared query parameters. Honors tier_id.
Example Request
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)
{
"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
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
| Parameter | Type | Description |
|---|---|---|
workspaceId | string (UUID) | Workspace identifier |
Query Parameters
See shared query parameters. Honors tier_id.
Example Request
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)
{
"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
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
| Parameter | Type | Description |
|---|---|---|
workspaceId | string (UUID) | Workspace identifier |
Query Parameters
See shared query parameters. Honors project_id.
Example Request
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)
{
"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
const report = await wh.reports.getPassesReport(workspaceId, {
from: "2026-05-01",
to: "2026-06-01",
project_id: projectId,
});