Earn Progress API
A way to earn can give its reward after every N times something happens: a free coffee after 10 purchases, 10 points after every 5 likes in a day. Bricqs counts each occurrence once, per member, in the merchant’s business calendar, and pays on the Nth. This endpoint is what a stamp card, a progress bar or your own screen reads.
Auth
All endpoints require an
X-API-Key header. Production keys are prefixed bq_live_; sandbox keys bq_test_.Scopes
Participant key Accepts an API key with gamify:read (mint default) or a participant JWT. A participant JWT can read its own progress only.
Admin scope Ways to earn are managed in the Builder under Loyalty, Ways to earn. There is no admin endpoint on this page.
Base URL
https://api.bricqs.co/api/v1/gamifyHow counting works. The occurrence is the event you send to
POST /gamify/events. Only events that pass the way to earn’s conditions count. A retried or replayed event never counts twice. The response of the event call shows a payout only on the Nth occurrence (rewards_granted); the stamps in between show here, not there.Endpoint inventory
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /gamify/participants/{participant_id}/earn-progress | Every active counted way to earn, with this member’s progress. |
GET
/api/v1/gamify/participants/{participant_id}/earn-progressParticipant key
Returns one item per active way to earn that pays after N occurrences, with the member's count in the current period, the payouts consumed, what is still needed, and whether a payout is owed.
Path parameters
| Field | Type | Description |
|---|---|---|
| participant_idrequired | str | Your participant identifier. 1 to 255 characters. |
GET /api/v1/gamify/participants/user_42/earn-progress
X-API-Key: bq_live_xxxxxResponse fields
| Field | Type | Description |
|---|---|---|
| items | list[EarnProgressItem] | One entry per active counted way to earn. Empty when the tenant has none. |
| items[].earn_rule_id | uuid | The way to earn. |
| items[].name | str | What members see: the name given in the Builder. |
| items[].event_name | str | null | The merchant's own event behind it, when it is one of their events. |
| items[].effect | object | What a full card gives: kind (points | reward), amount, reward_definition_id, reward_name. |
| items[].every | object | count (2 to 100000) and window (ever | day | week | month | year), the period in the merchant's business timezone. |
| items[].limit | object | null | How often the payout can be given, when the merchant set a cap: max_per_participant and window. |
| items[].presentation | object | null | The stamp icon: icon (one of check, star, heart, gift, coffee) or icon_url (an image in the merchant's media library). |
| items[].window_key | str | The current period: "ever", "2026-10-17", "2026-W42", "2026-10" or "2026". |
| items[].count | int | Occurrences counted in the current period. |
| items[].completed | int | Payouts consumed in the current period: delivered, or refused by the cap and never banked. |
| items[].delivered | int | Rewards really given to this member by this way to earn, over all time: read from the ledger and the claims, so an edit never changes it. |
| items[].remaining | int | Occurrences still needed for the next payout. 0 while a payout is owed. |
| items[].payout_pending | bool | True when the count has reached a payout that no action has delivered yet. The next occurrence tries again. |
| items[].done | bool | True when nothing more can be given on this card. |
| items[].done_reason | str | null | limit: the once-ever cap is used up (the reward was given). exhausted: the member already holds the reward's per-member maximum, so the card has nothing more to give. |
{
"items": [
{
"earn_rule_id": "7a1f...",
"name": "Coffee card",
"event_name": "coffee_bought",
"effect": { "kind": "reward", "amount": null, "reward_definition_id": "c0ff...", "reward_name": "Free coffee" },
"every": { "count": 10, "window": "ever" },
"limit": null,
"presentation": { "icon": "coffee", "icon_url": null },
"window_key": "ever",
"count": 7,
"completed": 0,
"delivered": 0,
"remaining": 3,
"payout_pending": false,
"done": false,
"done_reason": null
}
]
}Drawing a card. The stamps on the current card are
count - completed * every.count. After a delivered payout that is 0 again with completed one higher. When payout_pending is true, show every stamp lit and say the reward is on its way. When done is true, show every stamp lit and the reward as given: the card is complete for good.Errors
| Status | Code | When it fires |
|---|---|---|
| 401 | AUTH_UNAUTHENTICATED | X-API-Key header missing, invalid, expired, or revoked. |
| 403 | AUTH_FORBIDDEN | API key lacks gamify:read, a participant JWT asks for another participant, or the tenant is disabled. |
Related
Strategy guide
Sending the events that count →
When to use, KPIs, examples, common mistakes.
React SDK
useEarnProgress hook →
Hook signatures, props, auto-refresh behaviour.
