Appearance
A program's statistics
GET
/programs/{id}/stats
The numbers behind the dashboard's program page: cards, stamps, redemptions, completion rate, and the per-day / per-location / per-hour breakdowns. EVERY aggregate is nullable and that is the contract — each sub-query runs independently and returns null if it fails, so one broken aggregation degrades one widget instead of failing the call. Treat null as "unavailable", never as zero. timezone is the shop's, and every bucket is anchored to it.
Authorizations
ApiKeyBearer
A shop-scoped API key created in the dashboard and shown exactly once. An MCP tmk_ key presented here returns a 401 that names the mistake.
Type
HTTP (bearer)
Parameters
Path Parameters
id*
An opaque id. The API never promises an id format.
Type
Requiredstring
Responses
A program's statistics
application/json
JSON "active_cards": 1452, "total_stamps_awarded": 9310, "prizes_redeemed": 214, "completion_rate": 0.18, "cards_by_day": [ { "date": "2026-09-04", "count": 12 } ], "stamps_by_day": [ { "date": "2026-09-04", "count": 12 } ], "cards_by_location": [ { "location_id": "loc_docsfixture0001", "location_name": "Via Roma 1", "count": 12 } ], "stamps_by_location": [ { "location_id": "loc_docsfixture0001", "location_name": "Via Roma 1", "count": 12 } ], "stamps_by_hour_dow": [ { "day_of_week": 1, "hour": 9, "count": 12 } ], "platform_split": { "apple": 812, "google": 640 }, "avg_days_between_stamps": 6.4, "timezone": "Europe/Rome"
{
}
GET
/programs/{id}/stats