@smartico/public-api 0.0.402 → 0.0.404

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/.claude/skills/api-tsdoc/SKILL.md +675 -0
  2. package/.claude/skills/api-tsdoc-final/SKILL.md +266 -0
  3. package/.claude/skills/api-tsdoc-howto/SKILL.md +143 -0
  4. package/dist/MiniGames/SAWTemplate.d.ts +4 -0
  5. package/dist/NodeCache.d.ts +1 -0
  6. package/dist/OCache.d.ts +7 -0
  7. package/dist/SmarticoGlobal.d.ts +0 -6
  8. package/dist/WSAPI/WSAPITypes.d.ts +43 -0
  9. package/dist/WSAPI/WSAPIUser.d.ts +3 -0
  10. package/dist/index.js +92 -33
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.modern.mjs +60 -10
  13. package/dist/index.modern.mjs.map +1 -1
  14. package/docs/api/interfaces/TUserProfile.md +136 -0
  15. package/docs/capabilities/_responses/buyStoreItem.json +4 -0
  16. package/docs/capabilities/_responses/claimBonus.json +4 -0
  17. package/docs/capabilities/_responses/gamePickGetActiveRound.json +95 -0
  18. package/docs/capabilities/_responses/gamePickGetActiveRounds.json +191 -0
  19. package/docs/capabilities/_responses/gamePickGetBoard.json +47 -0
  20. package/docs/capabilities/_responses/gamePickGetGameInfo.json +355 -0
  21. package/docs/capabilities/_responses/gamePickGetHistory.json +191 -0
  22. package/docs/capabilities/_responses/gamePickGetUserInfo.json +14 -0
  23. package/docs/capabilities/_responses/getAchCategories.json +12 -0
  24. package/docs/capabilities/_responses/getActivityLog.json +1 -0
  25. package/docs/capabilities/_responses/getAvatarPrompts.json +16 -0
  26. package/docs/capabilities/_responses/getAvatarsCustomized.json +12 -0
  27. package/docs/capabilities/_responses/getAvatarsList.json +24 -0
  28. package/docs/capabilities/_responses/getBadges.json +98 -0
  29. package/docs/capabilities/_responses/getBonuses.json +18 -0
  30. package/docs/capabilities/_responses/getClanInfo.json +39 -0
  31. package/docs/capabilities/_responses/getClans.json +35 -0
  32. package/docs/capabilities/_responses/getCurrentLevel.json +20 -0
  33. package/docs/capabilities/_responses/getCustomSections.json +25 -0
  34. package/docs/capabilities/_responses/getInboxMessageBody.json +7 -0
  35. package/docs/capabilities/_responses/getInboxMessages.json +18 -0
  36. package/docs/capabilities/_responses/getInboxUnreadCount.json +1 -0
  37. package/docs/capabilities/_responses/getJackpotEligibleGames.json +20 -0
  38. package/docs/capabilities/_responses/getJackpotWinners.json +28 -0
  39. package/docs/capabilities/_responses/getLeaderBoard.json +45 -0
  40. package/docs/capabilities/_responses/getLevels.json +40 -0
  41. package/docs/capabilities/_responses/getMiniGames.json +208 -0
  42. package/docs/capabilities/_responses/getMiniGamesHistory.json +1 -0
  43. package/docs/capabilities/_responses/getMissions.json +117 -0
  44. package/docs/capabilities/_responses/getRaffleDrawRun.json +62 -0
  45. package/docs/capabilities/_responses/getRaffleDrawRunsHistory.json +34 -0
  46. package/docs/capabilities/_responses/getRaffles.json +140 -0
  47. package/docs/capabilities/_responses/getStoreCategories.json +12 -0
  48. package/docs/capabilities/_responses/getStoreItems.json +47 -0
  49. package/docs/capabilities/_responses/getStorePurchasedItems.json +49 -0
  50. package/docs/capabilities/_responses/getTournamentInstanceInfo.json +75 -0
  51. package/docs/capabilities/_responses/getTournamentsList.json +66 -0
  52. package/docs/capabilities/_responses/getTranslations.json +25 -0
  53. package/docs/capabilities/_responses/getUserLevelExtraCounters.json +4 -0
  54. package/docs/capabilities/_responses/getUserProfile.json +34 -0
  55. package/docs/capabilities/_responses/jackpotGet.json +113 -0
  56. package/docs/capabilities/_responses/jackpotOptIn.json +9 -0
  57. package/docs/capabilities/_responses/jackpotOptOut.json +9 -0
  58. package/docs/capabilities/_responses/markAllInboxMessagesAsRead.json +4 -0
  59. package/docs/capabilities/_responses/markInboxMessageAsRead.json +4 -0
  60. package/docs/capabilities/_responses/markUnmarkInboxMessageAsFavorite.json +4 -0
  61. package/docs/capabilities/_responses/miniGameWinAcknowledgeRequest.json +10 -0
  62. package/docs/capabilities/_responses/playMiniGame.json +6 -0
  63. package/docs/capabilities/_responses/playMiniGameBatch.json +9 -0
  64. package/docs/capabilities/_responses/registerInTournament.json +4 -0
  65. package/docs/capabilities/_responses/requestMissionOptIn.json +4 -0
  66. package/docs/capabilities/_responses/setAvatar.json +4 -0
  67. package/docs/capabilities/avatarsCustomize.md +115 -0
  68. package/docs/capabilities/buyStoreItem.md +179 -0
  69. package/docs/capabilities/checkSegmentListMatch.md +69 -0
  70. package/docs/capabilities/checkSegmentMatch.md +74 -0
  71. package/docs/capabilities/claimBonus.md +125 -0
  72. package/docs/capabilities/claimRafflePrize.md +116 -0
  73. package/docs/capabilities/deleteAllInboxMessages.md +66 -0
  74. package/docs/capabilities/deleteInboxMessage.md +60 -0
  75. package/docs/capabilities/gamePickGetActiveRound.md +248 -0
  76. package/docs/capabilities/gamePickGetActiveRounds.md +259 -0
  77. package/docs/capabilities/gamePickGetBoard.md +202 -0
  78. package/docs/capabilities/gamePickGetGameInfo.md +318 -0
  79. package/docs/capabilities/gamePickGetHistory.md +244 -0
  80. package/docs/capabilities/gamePickGetRoundInfoForUser.md +189 -0
  81. package/docs/capabilities/gamePickGetUserInfo.md +91 -0
  82. package/docs/capabilities/gamePickSubmitSelection.md +222 -0
  83. package/docs/capabilities/gamePickSubmitSelectionQuiz.md +198 -0
  84. package/docs/capabilities/getAchCategories.md +119 -0
  85. package/docs/capabilities/getActivityLog.md +108 -0
  86. package/docs/capabilities/getAvatarPrompts.md +81 -0
  87. package/docs/capabilities/getAvatarsCustomized.md +96 -0
  88. package/docs/capabilities/getAvatarsList.md +101 -0
  89. package/docs/capabilities/getBadges.md +237 -0
  90. package/docs/capabilities/getBonuses.md +159 -0
  91. package/docs/capabilities/getClanInfo.md +164 -0
  92. package/docs/capabilities/getClanTournamentPlayers.md +112 -0
  93. package/docs/capabilities/getClans.md +168 -0
  94. package/docs/capabilities/getCurrentLevel.md +123 -0
  95. package/docs/capabilities/getCustomSections.md +96 -0
  96. package/docs/capabilities/getInboxMessageBody.md +87 -0
  97. package/docs/capabilities/getInboxMessages.md +146 -0
  98. package/docs/capabilities/getInboxUnreadCount.md +54 -0
  99. package/docs/capabilities/getJackpotEligibleGames.md +93 -0
  100. package/docs/capabilities/getJackpotWinners.md +113 -0
  101. package/docs/capabilities/getLeaderBoard.md +187 -0
  102. package/docs/capabilities/getLeaderBoards.md +88 -0
  103. package/docs/capabilities/getLevels.md +118 -0
  104. package/docs/capabilities/getMiniGames.md +295 -0
  105. package/docs/capabilities/getMiniGamesHistory.md +183 -0
  106. package/docs/capabilities/getMissions.md +253 -0
  107. package/docs/capabilities/getRaffleDrawRun.md +210 -0
  108. package/docs/capabilities/getRaffleDrawRunsHistory.md +116 -0
  109. package/docs/capabilities/getRaffleWonPrizes.md +153 -0
  110. package/docs/capabilities/getRaffles.md +249 -0
  111. package/docs/capabilities/getRelatedItemsForGame.md +236 -0
  112. package/docs/capabilities/getStoreCategories.md +128 -0
  113. package/docs/capabilities/getStoreItems.md +260 -0
  114. package/docs/capabilities/getStorePurchasedItems.md +280 -0
  115. package/docs/capabilities/getTournamentInstanceInfo.md +301 -0
  116. package/docs/capabilities/getTournamentsList.md +234 -0
  117. package/docs/capabilities/getTranslations.md +95 -0
  118. package/docs/capabilities/getUserLevelExtraCounters.md +92 -0
  119. package/docs/capabilities/getUserProfile.md +184 -0
  120. package/docs/capabilities/jackpotGet.md +173 -0
  121. package/docs/capabilities/jackpotOptIn.md +94 -0
  122. package/docs/capabilities/jackpotOptOut.md +92 -0
  123. package/docs/capabilities/joinClan.md +169 -0
  124. package/docs/capabilities/markAllInboxMessagesAsRead.md +72 -0
  125. package/docs/capabilities/markInboxMessageAsRead.md +69 -0
  126. package/docs/capabilities/markUnmarkInboxMessageAsFavorite.md +75 -0
  127. package/docs/capabilities/miniGameWinAcknowledgeRequest.md +98 -0
  128. package/docs/capabilities/playMiniGame.md +217 -0
  129. package/docs/capabilities/playMiniGameBatch.md +129 -0
  130. package/docs/capabilities/registerInTournament.md +187 -0
  131. package/docs/capabilities/reportClickEvent.md +74 -0
  132. package/docs/capabilities/reportImpressionEvent.md +67 -0
  133. package/docs/capabilities/requestMissionClaimReward.md +117 -0
  134. package/docs/capabilities/requestMissionOptIn.md +98 -0
  135. package/docs/capabilities/requestRaffleOptin.md +108 -0
  136. package/docs/capabilities/setAvatar.md +132 -0
  137. package/docs/capabilities/smarticoCallbacks.md +165 -0
  138. package/docs/capabilities/smarticoGlobal.md +62 -0
  139. package/package.json +3 -2
  140. package/readme-smartico-dev.md +208 -0
  141. package/scripts/capture-responses-browser.mjs +301 -0
  142. package/scripts/gen-capabilities.js +368 -0
  143. package/scripts/run-public-api.mjs +105 -0
  144. package/src/MiniGames/SAWGetTemplatesResponse.ts +2 -0
  145. package/src/MiniGames/SAWTemplate.ts +5 -0
  146. package/src/NodeCache.ts +8 -0
  147. package/src/OCache.ts +17 -0
  148. package/src/SmarticoGlobal.ts +0 -7
  149. package/src/WSAPI/WSAPI.ts +3 -3
  150. package/src/WSAPI/WSAPIJackpots.ts +4 -1
  151. package/src/WSAPI/WSAPIMiniGames.ts +1 -1
  152. package/src/WSAPI/WSAPITypes.ts +44 -0
  153. package/src/WSAPI/WSAPIUser.ts +30 -5
@@ -0,0 +1,128 @@
1
+ # getStoreCategories — API (TStoreCategory)
2
+
3
+ > Returns the list of active store categories configured for the current label.
4
+ > Import: `import { TStoreCategory } from '@smartico/public-api'`
5
+ > Search terms: getStoreCategories, store, TStoreCategory, id, name, order
6
+
7
+ ## Signature
8
+ ```ts
9
+ _smartico.api.getStoreCategories(): Promise<TStoreCategory[]>
10
+ ```
11
+
12
+ ## Parameters
13
+ _None._
14
+
15
+ ## Returns — `Promise<TStoreCategory[]>`
16
+ Array of `TStoreCategory`. Each item:
17
+ - `id` (number) — ID of the store category
18
+ - `name` (string) — Name of the store category
19
+ - `order` (number) — Order of the store category among other categories. Default value is 1
20
+
21
+ ## Behavioral contract
22
+ **What categories are**
23
+ - Operator-defined groupings, configured per-label by the brand operator.
24
+ Only active categories are returned; inactive / archived / deleted ones are
25
+ filtered out server-side.
26
+ - Each `TStoreCategory` exposes `{ id, name, order }`. `name` is the display label;
27
+ `order` is the relative position (lower = appears first).
28
+ - The same set of categories is returned to every user of the label — there is no
29
+ per-segment / per-currency / per-device filtering on the category list. Item-level
30
+ segment visibility happens on `getStoreItems`, not here.
31
+
32
+ **Localization / translation**
33
+ - `name` is **pre-translated server-side** to the authenticated user's stored language.
34
+ In visitor mode, the language passed to `_smartico.vapi(lang)` drives the translation.
35
+ Consumers never need to translate `name` themselves.
36
+ - Fallback if no translation exists for the user's language: the operator-set default
37
+ (typically the brand's English) value is returned. The field is never null for an
38
+ active category.
39
+
40
+ **Sort order**
41
+ The server does NOT pre-sort. Sort client-side before rendering:
42
+ `categories.sort((a, b) => a.order - b.order)`.
43
+
44
+ **How store items join to categories**
45
+ Each `TStoreItem` exposes `category_ids: number[]` (zero-or-more, many-to-many).
46
+ A single store item can belong to multiple categories, or to none. To render a
47
+ "category → items" view:
48
+ `items.filter(i => i.category_ids.includes(cat.id))`.
49
+
50
+ **Uncategorized items**
51
+ Items with `category_ids: []` are NOT represented by a synthetic "Other" entry
52
+ in the response. The convention used by the reference store UI is to synthesize
53
+ a client-side bucket (e.g. labelled "General") for items that have no category, OR
54
+ for items whose `category_ids` reference a category that is no longer returned by
55
+ this method (e.g. archived since the item was tagged). If you choose to render
56
+ such a synthetic bucket, place it first (the reference UI uses an `order: -1`
57
+ convention so it precedes all operator-defined categories).
58
+
59
+ **Empty categories**
60
+ A category may be returned even if zero items currently reference it (since this
61
+ method does not join against items). The reference store UI hides such empty
62
+ categories from its tab strip — replicate that filter if you don't want to render
63
+ tabs that lead to empty content panels.
64
+
65
+ **Refresh cadence / cache**
66
+ - The SDK caches the response for 30 seconds. Subsequent calls within that window
67
+ return the cached array without a network round-trip.
68
+ - The cache is NOT invalidated by store-item push events or purchases — operator-driven
69
+ category changes propagate at the next 30 s cache miss.
70
+ - Cache is fully cleared on login / logout.
71
+ - In **visitor mode**, additional server-side caching applies on top of the SDK cache;
72
+ worst-case staleness for an edited/added category is on the order of a few minutes
73
+ for anonymous viewers.
74
+
75
+ **Idempotency**: safe. Read-only metadata fetch. Cache de-duplicates concurrent calls.
76
+
77
+ **Side effects**: none — pure metadata read.
78
+
79
+ **UI guidance**: see [UI Guide — `getStoreCategories`](../../docs/ui/store/UIGuide_getStoreCategories.md).
80
+
81
+ ## Example
82
+ ```ts
83
+ const [categories, items] = await Promise.all([
84
+ window._smartico.api.getStoreCategories(),
85
+ window._smartico.api.getStoreItems(),
86
+ ]);
87
+
88
+ if (categories.length === 0) {
89
+ console.log('[smartico] no store categories configured — render items as a flat grid without tabs:', items.length);
90
+ } else {
91
+ // Sort categories; build per-category item buckets; hide empty categories
92
+ const sorted = [...categories].sort((a, b) => a.order - b.order);
93
+ const tabs = sorted
94
+ .map(cat => ({ cat, items: items.filter(i => i.category_ids?.includes(cat.id)) }))
95
+ .filter(t => t.items.length > 0);
96
+
97
+ // Optional: synthesize an "Other" bucket for items with no (or unknown) category
98
+ const knownIds = new Set(categories.map(c => c.id));
99
+ const orphans = items.filter(i => !i.category_ids?.length || !i.category_ids.some(id => knownIds.has(id)));
100
+ if (orphans.length > 0) {
101
+ console.log('[smartico] uncategorized store items — render a client-synthesized "Other" tab at the front of the tab strip:', orphans.length);
102
+ }
103
+
104
+ console.log('[smartico] render store tabs in this order with these counts:', tabs.map(t => `${t.cat.name} (${t.items.length})`));
105
+ }
106
+
107
+ // Visitor mode — same shape, language driven by vapi(lang) argument
108
+ const visitorCats = await window._smartico.vapi('DE').getStoreCategories();
109
+ console.log('[smartico] visitor-mode store categories (names translated to DE):', visitorCats);
110
+ ```
111
+
112
+ ### Example response (REAL shape)
113
+ > Where this real payload differs from the typed Returns above (TS interface vs raw wire), the REAL shape is the runtime truth.
114
+ ```json
115
+ [
116
+ {
117
+ "id": 568,
118
+ "name": "Currency",
119
+ "order": 7
120
+ }
121
+ ]
122
+ ```
123
+
124
+ ## Errors
125
+ See this method's TSDoc / the mutation pages for `err_code` handling.
126
+
127
+ ## Related
128
+ - `getStoreItems`
@@ -0,0 +1,260 @@
1
+ # getStoreItems — API (TStoreItem)
2
+
3
+ > Returns the catalog of buyable store items visible to the current user, scoped server-side to what the user is qualified to see.
4
+ > Import: `import { TStoreItem } from '@smartico/public-api'`
5
+ > Search terms: getStoreItems, store, TStoreItem, TRibbon, AchRelatedGame, onUpdate, subscription, id, name, purchase_type, price, image, description, ribbon, priority
6
+
7
+ ## Signature
8
+ ```ts
9
+ _smartico.api.getStoreItems({ onUpdate }: { onUpdate?: (data: TStoreItem[]) => void } = {}): Promise<TStoreItem[]>
10
+ ```
11
+
12
+ ## Parameters
13
+ - `params` — Optional. Omit to fetch without subscribing.
14
+ - `params.onUpdate` — Callback invoked with the full refreshed catalog after every `buyStoreItem`round-trip on this connection. Each call to `getStoreItems` overwrites the prior callback. Never fires in visitor mode.
15
+
16
+ ## Returns — `Promise<TStoreItem[]>`
17
+ Array of `TStoreItem`. Each item:
18
+ - `id` (number) — ID of the store item
19
+ - `name` (string) — Name of the store item, translated to the user language
20
+ - `description` (string) — Description of the store item, translated to the user language
21
+ - `image` (string) — URL of the image of the store item, 256x256px
22
+ - `type` ('bonus' | 'tangible' | 'minigamespin' | 'changelevel' | 'prizedrop' | 'unknown' | 'raffleticket') — Type of the store item. Can be 'bonus' or 'tangible' or different others.
23
+ - `price` (number) — The price of the store item in the gamification points
24
+ - `ribbon` (TRibbon) — The ribbon of the store item. Can be 'sale', 'hot', 'new', 'vip' or URL to the image in case of custom ribbon, 250x300px
25
+ - `limit_message` (string) — The message that should be shown to the user if he is not eligible to buy it. this message can be used to explain the reason why user cannot buy the item, e.g. 'You should be VIP to buy this item' and can be used in case can_buy property is false. The message is translated to the user language. *Note**: when user is trying to buy the item, the response from server can return custom error messages that can be shown to the user as well
26
+ - `purchase_limit_message` (string) — The message that should be shown to the user if they are not eligible to buy it because of purchase limitation. This message can be used to explain the reason why user cannot buy the item, e.g. 'Item is no more available today. Come back Friday'. The message is translated to the user language. *Note**: when user is trying to buy the item, the response from server can return custom error messages that can be shown to the user as well
27
+ - `priority` (number) — The priority of the store item. Can be used to sort the items in the store
28
+ - `related_item_ids` (number[]) — The list of IDs of the related items. Can be used to show the related items in the store
29
+ - `related_games` (AchRelatedGame[]) — List of casino games (or other types of entities) related to the store item
30
+ - `ext_game_id` (string) — The ID of the related game
31
+ - `game_public_meta` ({
32
+ /** The name of the game */
33
+ name: string;
34
+ /** The URL to the game */
35
+ link: string;
36
+ /** The URL to the image of the game, 1:1 aspect ratio */
37
+ image: string;
38
+ /** The indicator if the game is enabled */
39
+ enabled: boolean;
40
+ /** The list of categories of the game */
41
+ game_categories: string[];
42
+ /** The name of the game provider */
43
+ game_provider: string;
44
+ /** The URL to the mobile game */
45
+ mobile_spec_link: string;
46
+ /** The priority of the game */
47
+ priority?: number;
48
+ }) — Game public meta information
49
+ - `can_buy` (boolean) — The indicator if the user can buy the item This indicator is taking into account the segment conditions for the store item, the price of item towards users balance,
50
+ - `category_ids` (number[]) — The list of IDs of the categories where the store item is assigned, information about categories can be retrieved with getStoreCategories method
51
+ - `pool` (number) — Items remaining in the pool available for purchase. `null` = unlimited supply. Positive integer = remaining stock. `0` = sold out but still returned (operator may instead hide pool-empty items entirely).
52
+ - `custom_data` (any) — The custom data of the store item defined by operator. Can be a JSON object, string or number
53
+ - `hint_text` (string) — The T&C text for the store item
54
+ - `purchase_ts` (number) — Purchase time to show in purchase history screen
55
+ - `purchase_points_amount` (number) — The amount of points you can purchase an item
56
+ - `purchased_today` (boolean) — Flag for store item indicating that it was purchased today
57
+ - `purchased_this_week` (boolean) — Flag for store item indicating that it was purchased this week
58
+ - `purchased_this_month` (boolean) — Flag for store item indicating that it was purchased this month
59
+ - `purchase_type` ('points' | 'gems' | 'diamonds') — The type of the purchase
60
+ - `active_till_date` (number) — The date when the store item will be available till
61
+ - `show_timer` (boolean) — Should countdown timer be shown when `active_till_date` is present
62
+ - `discounted_price` (number) — The discounted price of the store item
63
+ - `discount_price_ribbon` (string) — The ribbon of the discounted price.
64
+ - `custom_ribbon_image` (string) — The custom ribbon image of the discounted price, 250x300px
65
+ - `custom_section_id` (number) — The ID of the custom section where the store item is assigned
66
+ - `only_in_custom_section` (boolean) — The indicator if the store item is visible only in the custom section and should be hidden from the main overview of store items
67
+ - `custom_section_type_id` (number) — ID of specific Custom Section type
68
+ - `cant_buy_message` (string) — The message that should be shown to the user if they are not eligible to buy it. This message can be used to explain the reason why user cannot buy the item, e.g. 'You should be VIP to buy this item'.
69
+
70
+ ## Behavioral contract
71
+ **Preconditions**
72
+ The catalog is per-user. Visitor mode is supported with caveats (see
73
+ "Visitor mode" below). For the authenticated path, the user's balances
74
+ (`ach_points_balance`, `ach_gems_balance`, `ach_diamonds_balance` from
75
+ `getUserProfile`) must be tracked client-side to drive the
76
+ affordability state of the Buy button — the SDK does not pre-compute
77
+ affordability into `can_buy`.
78
+
79
+ **Subscription model (`onUpdate`)**
80
+ The callback receives the FULL refreshed catalog (never a diff/patch).
81
+ Each subsequent call to `getStoreItems({ onUpdate })` REPLACES the prior
82
+ callback — only one active subscriber at a time. Pass
83
+ `onUpdate: undefined` (or omit it) to keep the prior callback in place;
84
+ the callback is never auto-cleared.
85
+
86
+ **Update triggers**
87
+
88
+ Fires after: any `buyStoreItem(...)` call resolves on this connection
89
+ (success OR failure). This is the ONLY trigger. The refreshed array
90
+ reflects pool decrement on the just-bought item, per-period purchase
91
+ cap re-evaluation on `can_buy`, and any `purchased_today` /
92
+ `purchased_this_week` / `purchased_this_month` flips visible via
93
+ `getStorePurchasedItems`.
94
+
95
+ Does NOT fire for:
96
+ - Operator-side BO catalog edits (price, ribbons, pool seed, segment
97
+ conditions, new/removed items) — surface only on the next cache miss.
98
+ - Concurrent purchases by OTHER users — the current user's view of
99
+ `pool` may be stale until they themselves refresh.
100
+ - User balance changes from gameplay — the catalog is independent of
101
+ balance; the consumer drives Buy-button affordability from a
102
+ separately-tracked balance source.
103
+ - Items going past their `active_till_date` while the page is open —
104
+ the item simply disappears on the next refresh.
105
+
106
+ **Server-side filtering** (what's already excluded before the SDK sees it)
107
+ - Items outside the `[active_from_date, active_till_date]` window —
108
+ past the till-date, items are ALWAYS filtered out server-side.
109
+ - Items the user fails visibility-segment / visibility-condition
110
+ checks for.
111
+ - Items configured to hide-when-empty whose pool has reached 0
112
+ (per-item operator flag). Items without that flag are still returned
113
+ with `pool === 0` so a "Sold out" state can be rendered.
114
+ - Items where the per-period bought-count cap is reached (and the
115
+ operator chose to hide rather than just disable).
116
+
117
+ **Reading state from the returned item**
118
+ The catalog row carries everything a Buy button needs except the user's
119
+ balance: `can_buy` already reflects segment / visibility / per-period
120
+ cap checks, but the SDK does NOT pre-compute balance affordability —
121
+ compare `discounted_price ?? price` against the user's balance for
122
+ `purchase_type` (`ach_points_balance` / `ach_gems_balance` /
123
+ `ach_diamonds_balance` from `getUserProfile`). `purchase_type` is
124
+ per-item (`'points'` / `'gems'` / `'diamonds'`); operators can mix
125
+ currencies within a single catalog. For sold-out display, `pool === 0`
126
+ means the operator chose to keep the item visible — render an "Out of
127
+ stock" overlay. When `discounted_price` is set, render `price` with a
128
+ strikethrough and `discounted_price` as the active price; the
129
+ accompanying `discount_price_ribbon` is either a percentage preset
130
+ (`'10'`, `'15'`, `'20'`, `'25'`, `'50'`) or the literal `'custom'`
131
+ (in which case `custom_ribbon_image` is the artwork at 250×300 px).
132
+ A live countdown for time-limited items is rendered only when the
133
+ operator has enabled the per-item `show_timer` flag.
134
+
135
+ **Cross-references**
136
+ `category_ids` joins to `TStoreCategory.id` from
137
+ `getStoreCategories` (many-to-many — an item can belong to
138
+ multiple categories). Items with `only_in_custom_section: true` are
139
+ returned in the catalog but intended for their custom-section view
140
+ only — filter them client-side for the main store view. The
141
+ history-only fields (`purchase_ts`, `purchase_points_amount`, the
142
+ `purchased_*` booleans) are populated only by
143
+ `getStorePurchasedItems`, not by this method.
144
+
145
+ **Idempotency**: yes. `getStoreItems` is a pure read. Calling it
146
+ repeatedly within the 30-second cache window resolves from the cache
147
+ without a network round-trip.
148
+
149
+ **Side effects** (of a successful purchase that triggers `onUpdate`)
150
+ Documented here because the consumer's `onUpdate` handler will observe
151
+ the resulting state changes on the next refreshed array:
152
+ - Points / gems / diamonds balance deducted per `purchase_type`. The
153
+ new balance becomes visible on the user's gamification profile via
154
+ the SDK's user-properties update channel (`ach_points_balance` /
155
+ `ach_gems_balance` / `ach_diamonds_balance`).
156
+ - `pool` decremented for limited-stock items.
157
+ - `type = 'bonus'` → a CRM bonus is granted; surfaces via
158
+ `getBonuses`.
159
+ - `type = 'raffleticket'` → raffle tickets granted; surfaces via
160
+ `getRaffles`.
161
+ - `type = 'changelevel'` → user's level adjusted; surfaces via
162
+ `getCurrentLevel`.
163
+ - `type = 'minigamespin'` → SAW spin attempts granted; visible via the
164
+ mini-game APIs.
165
+ - `type = 'prizedrop'` → one prize-drop attempt granted.
166
+ - `type = 'tangible'` → no automatic gameplay effect; the purchase is
167
+ recorded for the operator's manual fulfillment (e.g. physical merch).
168
+
169
+ **UI guidance**: see [UI Guide — `getStoreItems`](../../docs/ui/store/UIGuide_getStoreItems.md).
170
+
171
+ ## Example
172
+ ```ts
173
+ // 1. Initial fetch + subscribe to live updates
174
+ const items = await window._smartico.api.getStoreItems({
175
+ onUpdate: (refreshed) => {
176
+ console.log('[smartico] store catalog refreshed after a purchase — re-render the entire store UI from this array, do not merge with prior state:', refreshed);
177
+
178
+ // 2. onUpdate fires only after the current user's own purchase
179
+ // round-trip. Pool counts and can_buy flags are now current
180
+ // for this user.
181
+ const soldOut = refreshed.filter(i => i.pool === 0);
182
+ if (soldOut.length > 0) {
183
+ console.log('[smartico] these items are now sold out — render an "Out of stock" overlay on each:', soldOut.map(i => i.id));
184
+ }
185
+ },
186
+ });
187
+
188
+ // 3. Live affordability per item. Compare each item's price against
189
+ // the user's balance for its purchase_type (read from
190
+ // getUserProfile(), kept live by the SDK's user-properties channel).
191
+ const profile = window._smartico.api.getUserProfile();
192
+ const balances = {
193
+ points: profile?.ach_points_balance ?? 0,
194
+ gems: profile?.ach_gems_balance ?? 0,
195
+ diamonds: profile?.ach_diamonds_balance ?? 0,
196
+ };
197
+
198
+ // 4. Filter out items that are custom-section-only for the main view.
199
+ const mainViewItems = items.filter(i => !i.only_in_custom_section);
200
+
201
+ // 5. Bucket each item's button state for rendering.
202
+ for (const i of mainViewItems) {
203
+ const activePrice = i.discounted_price ?? i.price;
204
+ const canAfford = balances[i.purchase_type] >= activePrice;
205
+ if (i.pool === 0) {
206
+ console.log('[smartico] item', i.id, 'is sold out — render disabled Buy with "Out of stock" overlay');
207
+ } else if (i.can_buy === false) {
208
+ console.log('[smartico] item', i.id, 'is not eligible — render disabled Buy and surface cant_buy_message on the popup:', i.cant_buy_message);
209
+ } else if (!canAfford) {
210
+ console.log('[smartico] item', i.id, 'is unaffordable — render disabled Buy and show "short by" line on popup; deficit =', activePrice - balances[i.purchase_type], i.purchase_type);
211
+ } else {
212
+ console.log('[smartico] item', i.id, 'is buyable — render enabled Buy at price', activePrice, i.purchase_type);
213
+ }
214
+ }
215
+
216
+ // 6. Visitor-mode equivalent: onUpdate is accepted but never fires.
217
+ // Re-poll if you need fresh data; buyStoreItem is not supported.
218
+ // const visitorItems = await window._smartico.vapi('EN').getStoreItems();
219
+ // console.log('[smartico] visitor catalog is the brand proxy user\'s — per-user fields are not meaningful');
220
+ ```
221
+
222
+ ### Example response (REAL shape)
223
+ > Where this real payload differs from the typed Returns above (TS interface vs raw wire), the REAL shape is the runtime truth.
224
+ ```json
225
+ [
226
+ {
227
+ "id": 7771,
228
+ "name": "Do not the cat",
229
+ "purchase_type": "points",
230
+ "price": 69,
231
+ "image": "https://cdn.example/83109b74be861920197eb8-cat-space.gif",
232
+ "description": "Please do not the cat",
233
+ "ribbon": "hot",
234
+ "priority": 10,
235
+ "type": "unknown",
236
+ "can_buy": false,
237
+ "category_ids": [
238
+ 234
239
+ ],
240
+ "pool": 69,
241
+ "custom_data": {},
242
+ "active_till_date": 9223372036854776000,
243
+ "show_timer": false,
244
+ "only_in_custom_section": false,
245
+ "cant_buy_message": "Please do not the cat. Thank you.",
246
+ "related_games": []
247
+ }
248
+ ]
249
+ ```
250
+
251
+ ## Errors
252
+ See this method's TSDoc / the mutation pages for `err_code` handling.
253
+
254
+ ## Related
255
+ - `getUserProfile`
256
+ - `getStorePurchasedItems`
257
+ - `getStoreCategories`
258
+ - `getBonuses`
259
+ - `getCurrentLevel`
260
+ - `buyStoreItem`
@@ -0,0 +1,280 @@
1
+ # getStorePurchasedItems — API (TStoreItem)
2
+
3
+ > Fetches the authenticated user's **store purchase history** — a paginated, newest-first list of past store purchases (one row per redemption).
4
+ > Import: `import { TStoreItem } from '@smartico/public-api'`
5
+ > Search terms: getStorePurchasedItems, store, TStoreItem, TRibbon, AchRelatedGame, onUpdate, subscription, id, name, price, purchase_type, image, description, ribbon, priority
6
+
7
+ ## Signature
8
+ ```ts
9
+ _smartico.api.getStorePurchasedItems({
10
+ limit,
11
+ offset,
12
+ onUpdate,
13
+ }: { limit?: number; offset?: number; onUpdate?: (data: TStoreItem[]) => void } = {}): Promise<TStoreItem[]>
14
+ ```
15
+
16
+ ## Parameters
17
+ - `params` — - Optional pagination + callback bag.
18
+ - `params.limit` — - Page size. Defaults to `20`. Use `20` as the conventional value (matches the default Smartico UI end-to-end). Avoid non-positive values.
19
+ - `params.offset` — - Number of rows to skip from the newest end. Defaults to `0`. For load-more pagination pass the current array length.
20
+ - `params.onUpdate` — - Optional callback invoked after a successful `buyStoreItem` elsewhere in the session. Receives the refreshed page for the same `(limit, offset)` used on the call that registered this callback. Only ONE callback can be registered; each new call overwrites the previous one. Pass a stable handler or re-register intentionally on screen entry.
21
+
22
+ ## Returns — `Promise<TStoreItem[]>`
23
+ Array of `TStoreItem`. Each item:
24
+ - `id` (number) — ID of the store item
25
+ - `name` (string) — Name of the store item, translated to the user language
26
+ - `description` (string) — Description of the store item, translated to the user language
27
+ - `image` (string) — URL of the image of the store item, 256x256px
28
+ - `type` ('bonus' | 'tangible' | 'minigamespin' | 'changelevel' | 'prizedrop' | 'unknown' | 'raffleticket') — Type of the store item. Can be 'bonus' or 'tangible' or different others.
29
+ - `price` (number) — The price of the store item in the gamification points
30
+ - `ribbon` (TRibbon) — The ribbon of the store item. Can be 'sale', 'hot', 'new', 'vip' or URL to the image in case of custom ribbon, 250x300px
31
+ - `limit_message` (string) — The message that should be shown to the user if he is not eligible to buy it. this message can be used to explain the reason why user cannot buy the item, e.g. 'You should be VIP to buy this item' and can be used in case can_buy property is false. The message is translated to the user language. *Note**: when user is trying to buy the item, the response from server can return custom error messages that can be shown to the user as well
32
+ - `purchase_limit_message` (string) — The message that should be shown to the user if they are not eligible to buy it because of purchase limitation. This message can be used to explain the reason why user cannot buy the item, e.g. 'Item is no more available today. Come back Friday'. The message is translated to the user language. *Note**: when user is trying to buy the item, the response from server can return custom error messages that can be shown to the user as well
33
+ - `priority` (number) — The priority of the store item. Can be used to sort the items in the store
34
+ - `related_item_ids` (number[]) — The list of IDs of the related items. Can be used to show the related items in the store
35
+ - `related_games` (AchRelatedGame[]) — List of casino games (or other types of entities) related to the store item
36
+ - `ext_game_id` (string) — The ID of the related game
37
+ - `game_public_meta` ({
38
+ /** The name of the game */
39
+ name: string;
40
+ /** The URL to the game */
41
+ link: string;
42
+ /** The URL to the image of the game, 1:1 aspect ratio */
43
+ image: string;
44
+ /** The indicator if the game is enabled */
45
+ enabled: boolean;
46
+ /** The list of categories of the game */
47
+ game_categories: string[];
48
+ /** The name of the game provider */
49
+ game_provider: string;
50
+ /** The URL to the mobile game */
51
+ mobile_spec_link: string;
52
+ /** The priority of the game */
53
+ priority?: number;
54
+ }) — Game public meta information
55
+ - `can_buy` (boolean) — The indicator if the user can buy the item This indicator is taking into account the segment conditions for the store item, the price of item towards users balance,
56
+ - `category_ids` (number[]) — The list of IDs of the categories where the store item is assigned, information about categories can be retrieved with getStoreCategories method
57
+ - `pool` (number) — Items remaining in the pool available for purchase. `null` = unlimited supply. Positive integer = remaining stock. `0` = sold out but still returned (operator may instead hide pool-empty items entirely).
58
+ - `custom_data` (any) — The custom data of the store item defined by operator. Can be a JSON object, string or number
59
+ - `hint_text` (string) — The T&C text for the store item
60
+ - `purchase_ts` (number) — Purchase time to show in purchase history screen
61
+ - `purchase_points_amount` (number) — The amount of points you can purchase an item
62
+ - `purchased_today` (boolean) — Flag for store item indicating that it was purchased today
63
+ - `purchased_this_week` (boolean) — Flag for store item indicating that it was purchased this week
64
+ - `purchased_this_month` (boolean) — Flag for store item indicating that it was purchased this month
65
+ - `purchase_type` ('points' | 'gems' | 'diamonds') — The type of the purchase
66
+ - `active_till_date` (number) — The date when the store item will be available till
67
+ - `show_timer` (boolean) — Should countdown timer be shown when `active_till_date` is present
68
+ - `discounted_price` (number) — The discounted price of the store item
69
+ - `discount_price_ribbon` (string) — The ribbon of the discounted price.
70
+ - `custom_ribbon_image` (string) — The custom ribbon image of the discounted price, 250x300px
71
+ - `custom_section_id` (number) — The ID of the custom section where the store item is assigned
72
+ - `only_in_custom_section` (boolean) — The indicator if the store item is visible only in the custom section and should be hidden from the main overview of store items
73
+ - `custom_section_type_id` (number) — ID of specific Custom Section type
74
+ - `cant_buy_message` (string) — The message that should be shown to the user if they are not eligible to buy it. This message can be used to explain the reason why user cannot buy the item, e.g. 'You should be VIP to buy this item'.
75
+
76
+ ## Behavioral contract
77
+ **Preconditions**
78
+ - User must be authenticated. Visitor mode is not supported (the SDK only
79
+ exposes this method on the authenticated `_smartico.api`, not on
80
+ `_smartico.vapi`).
81
+ - No prerequisite calls — calling without first fetching
82
+ `getStoreItems` or `getStoreCategories` is fine.
83
+
84
+ **Pagination semantics**
85
+ - **Offset-based**, newest-first. The server orders rows by purchase
86
+ timestamp **descending** and the SDK does NOT re-sort — items arrive
87
+ ready to render in display order.
88
+ - `limit` — page size. **The SDK default is 20.** There is no server-side
89
+ hard cap, but 20 matches what the default Smartico UI uses end-to-end; the
90
+ protocol and storage layers were sized for this page size. Treat `20`
91
+ as the conventional/recommended value; passing a much larger limit will
92
+ return more rows but is not the supported integration pattern.
93
+ Avoid `limit <= 0` — the server peeks `limit + 1` rows internally, so
94
+ `limit = 0` returns 1 row with a misleading "has more" signal, and
95
+ negative values produce undefined results.
96
+ - `offset` — number of items to skip from the start. The SDK default is
97
+ `0` (first page). For load-more pagination, pass
98
+ `offset = (previously-loaded items).length` on each subsequent call.
99
+ - **No `hasMore` on the returned array.** `TStoreItem[]` is a flat list;
100
+ the underlying protocol response carries `hasMore` but it is not
101
+ surfaced through this method. Two ways for consumers to know they
102
+ reached the end:
103
+ 1. The returned array is shorter than `limit` (definitive end), or
104
+ 2. A subsequent call at `offset = previous.length` returns `[]`.
105
+ Either is reliable.
106
+ - No date-range / category / status filter parameters — pagination is the
107
+ only server-side slicing. Apply any further filtering client-side.
108
+
109
+ **No per-item fulfillment status**
110
+ - History entries do NOT carry a `delivered` / `pending` / `cancelled` /
111
+ `refunded` field. The list contains rows for committed purchase
112
+ attempts; the server query does not filter by transaction-status, so in
113
+ practice the rows that appear are completed purchases (failed
114
+ transactions roll back and don't write a row). Treat every item as a
115
+ completed transaction unless a future SDK release adds an explicit
116
+ status field.
117
+
118
+ **Bonus-type entries**
119
+ - When the user redeemed a bonus item, the entry's `type` field surfaces
120
+ as `'bonus'`. **Known limitation:** the SDK transform currently maps
121
+ both `Bonus` and `Tangible` server-side item types to the same string
122
+ `'bonus'` — so the `type` field on history rows cannot distinguish a
123
+ bonus redemption from a tangible-prize redemption. The actual bonus
124
+ payload (wallet credit, free spins, etc.) is dispatched by the server
125
+ asynchronously and is NOT embedded in the history entry — consumers
126
+ that need bonus details should subscribe to bonus push events
127
+ separately rather than reading them from this list.
128
+ - History rows render identically across types — there is no deep-link to
129
+ the bonus wallet or re-claim affordance on the row itself.
130
+
131
+ **Per-row data**
132
+ Each row uses the `TStoreItem` shape but populates four history-only
133
+ fields not present on `getStoreItems` output. `purchase_ts` is the
134
+ Unix-ms timestamp of the purchase — format with
135
+ `new Date(purchase_ts).toLocaleString()` in the user's local timezone;
136
+ no relative labels ("Today" / "Yesterday") are produced by the SDK.
137
+ `purchase_points_amount` is the amount actually paid at the time of
138
+ purchase — a snapshot of the historical price, which may differ from
139
+ the item's current `price`. `purchase_type` is the currency actually
140
+ charged (`'points' | 'gems' | 'diamonds'`); render the matching
141
+ balance icon next to the amount. The convenience booleans
142
+ `purchased_today` / `purchased_this_week` / `purchased_this_month` are
143
+ computed client-side from the consumer's local clock — useful for
144
+ grouping rows under "Today" / "This Week" headers.
145
+
146
+ **Catalog fields on a history row**
147
+ The promotional fields (`ribbon`, `discounted_price`,
148
+ `discount_price_ribbon`, `custom_ribbon_image`, `active_till_date`)
149
+ reflect the CURRENT catalog state of the item, NOT its state at
150
+ purchase time — the default Smartico UI hides them on history rows to
151
+ avoid implying that the historical purchase carried the current
152
+ promotional banner. Descriptive marketing fields (`description`,
153
+ `hint_text`, `related_games`) are typically suppressed on a compact
154
+ history row. The current-purchasability fields `can_buy` and `pool`
155
+ reflect now, not then — useful only if you render a "Buy Again"
156
+ affordance on the row. One implementation gotcha: unlike
157
+ `getStoreItems`, this method's transform does NOT auto-parse JSON
158
+ strings in `custom_data` — call `JSON.parse()` yourself if you store
159
+ JSON there.
160
+
161
+ **Cache & refresh**
162
+ - The SDK caches each `(limit, offset)` page separately for 30 seconds.
163
+ Repeated calls within that window resolve from cache without a
164
+ network round-trip.
165
+ - The cache is invalidated and `onUpdate` (when registered) is invoked
166
+ automatically after a successful `buyStoreItem` call — the SDK
167
+ re-fetches the same page parameters that were registered together with
168
+ the current `onUpdate` callback and pushes the fresh array.
169
+ - Multi-tab caveat: if the user has the same brand open in multiple
170
+ tabs, **all open tabs** receive the `onUpdate` event on a purchase,
171
+ not only the tab that initiated the buy. The event is scoped to the
172
+ current authenticated user — a different user's purchase never fires
173
+ this callback.
174
+ - Only ONE `onUpdate` callback can be registered at a time. Each call to
175
+ `getStorePurchasedItems({ onUpdate })` overwrites the previous handler.
176
+
177
+ **Idempotency**: safe. Pure read.
178
+
179
+ **Side effects**: none — read-only.
180
+
181
+ **UI guidance**: see [UI Guide — `getStorePurchasedItems`](../../docs/ui/store/UIGuide_getStorePurchasedItems.md).
182
+
183
+ ## Example
184
+ ```ts
185
+ // Initial load + subscribe to refresh-on-purchase.
186
+ const handleHistoryUpdate = (items: TStoreItem[]) => {
187
+ console.log(
188
+ '[smartico] purchase history refreshed — re-render the history list with these',
189
+ items.length,
190
+ 'items (newest first):',
191
+ items,
192
+ );
193
+ };
194
+
195
+ try {
196
+ const firstPage = await _smartico.api.getStorePurchasedItems({
197
+ limit: 20,
198
+ offset: 0,
199
+ onUpdate: handleHistoryUpdate,
200
+ });
201
+
202
+ if (firstPage.length === 0) {
203
+ console.log('[smartico] no purchase history — render the empty state ("No purchases yet")');
204
+ } else {
205
+ console.log(
206
+ '[smartico] render',
207
+ firstPage.length,
208
+ 'history rows (newest first). Show "Load more" button if length === 20:',
209
+ firstPage,
210
+ );
211
+
212
+ // Inspect the first entry's history-only fields.
213
+ const first = firstPage[0];
214
+ console.log(
215
+ '[smartico] most-recent purchase: name=', first.name,
216
+ 'paid', first.purchase_points_amount, first.purchase_type,
217
+ 'at', new Date(first.purchase_ts ?? 0).toLocaleString(),
218
+ '— format with toLocaleString (user-local time) on the row.',
219
+ );
220
+ }
221
+
222
+ // Load-more pattern: fetch page 2 once the user scrolls / clicks "Load more".
223
+ if (firstPage.length === 20) {
224
+ const nextPage = await _smartico.api.getStorePurchasedItems({
225
+ limit: 20,
226
+ offset: firstPage.length,
227
+ });
228
+ const isLastPage = nextPage.length < 20;
229
+ console.log(
230
+ '[smartico] appended page 2 —',
231
+ nextPage.length,
232
+ 'rows.',
233
+ isLastPage ? 'Hide "Load more" — end reached.' : 'Keep "Load more" visible.',
234
+ );
235
+ }
236
+ } catch (e) {
237
+ console.error(
238
+ '[smartico] failed to load purchase history — show a generic error placeholder or retry with backoff:',
239
+ e,
240
+ );
241
+ }
242
+ ```
243
+
244
+ ### Example response (REAL shape)
245
+ > Where this real payload differs from the typed Returns above (TS interface vs raw wire), the REAL shape is the runtime truth.
246
+ ```json
247
+ [
248
+ {
249
+ "id": 7158,
250
+ "name": "Okayish Drop",
251
+ "price": 25,
252
+ "purchase_type": "points",
253
+ "image": "https://cdn.example/33fa1a793eac4a807041ac-Gamificationpoints10.webp",
254
+ "description": "A chance to win one out of 6 totally fine prizes",
255
+ "ribbon": "sale",
256
+ "priority": 3,
257
+ "type": "prizedrop",
258
+ "can_buy": true,
259
+ "category_ids": [
260
+ 567
261
+ ],
262
+ "pool": 1000,
263
+ "purchase_ts": 1781880583706,
264
+ "purchase_points_amount": 25,
265
+ "purchased_today": false,
266
+ "purchased_this_week": false,
267
+ "purchased_this_month": true,
268
+ "show_timer": false,
269
+ "related_games": []
270
+ }
271
+ ]
272
+ ```
273
+
274
+ ## Errors
275
+ See this method's TSDoc / the mutation pages for `err_code` handling.
276
+
277
+ ## Related
278
+ - `getStoreItems`
279
+ - `getStoreCategories`
280
+ - `buyStoreItem`