@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,217 @@
1
+ # playMiniGame — API (TMiniGamePlayResult)
2
+
3
+ > Plays one round of a mini-game template — runs the server's randomised prize selection, deducts the buy-in cost (if any), credits the won prize, and returns the won `prize_id`.
4
+ > Import: `import { TMiniGamePlayResult } from '@smartico/public-api'`
5
+ > Search terms: playMiniGame, minigames, doSAWSpin, SAWSpin, spin, TMiniGamePlayResult, SAWSpinErrorCode, onUpdate, subscription, err_code, err_message, prize_id, request_id
6
+
7
+ ## Signature
8
+ ```ts
9
+ _smartico.api.playMiniGame(template_id: number, { onUpdate, acknowledge = true }: { onUpdate?: (data: TMiniGameTemplate[]) => void, acknowledge?: boolean } = {}): Promise<TMiniGamePlayResult>
10
+ ```
11
+
12
+ ## Parameters
13
+ - `template_id` — The mini-game template ID (from `TMiniGameTemplate.id`).
14
+ - `params` — Optional options bag.
15
+ - `params.onUpdate` — Pass a callback to subscribe to subsequent template refreshes (same channel as `getMiniGames`).
16
+ - `params.acknowledge` — Whether the SDK automatically sends and awaits the win acknowledge after the spin. Defaults to `true` (recommended). Set `false` to finalise the win yourself via `miniGameWinAcknowledgeRequest`— see "Acknowledge" above for the request-id caveat.
17
+
18
+ ## Returns — `Promise<TMiniGamePlayResult>`
19
+ `TMiniGamePlayResult`:
20
+ - `err_code` (SAWSpinErrorCode) — Error code. `0` = success (`SAWSpinErrorCode.SAW_OK`). See `playMiniGame` TSDoc for the full table.
21
+ - `err_message` (string) — Optional server-side error message. Present only on non-zero `err_code`; may be empty even then.
22
+ - `prize_id` (number) — ID of the won prize. Look up in `template.prizes` to interpret (including `prize_type === 'no-prize'` for a configured loss slot). Always populated, even when `err_code !== 0`.
23
+ - `request_id` (string) — Correlation id of this spin. Pass it to `miniGameWinAcknowledgeRequest` to finalise the win when playing with `acknowledge: false` — no need to look it up via `getMiniGamesHistory`.
24
+
25
+ ## Behavioral contract
26
+ **Preconditions**
27
+ Read the candidate template from `getMiniGames` and check:
28
+ - `spin_count > 0` for spin-based templates
29
+ (`saw_buyin_type === 'spins'`).
30
+ - Sufficient balance for paid templates — points / gems /
31
+ diamonds from `getUserProfile` against
32
+ `buyin_cost_points` / `_gems` / `_diamonds`.
33
+ - `next_available_spin_ts` is in the past (or unset) — the
34
+ server enforces a per-period max-attempts cap.
35
+ - Template is currently in its active period
36
+ (operator-configured `activeFromDate` / `activeTillDate`).
37
+
38
+
39
+
40
+ **Prize handling**
41
+ On `err_code === 0`, `prize_id` matches an entry in
42
+ `template.prizes`. Look up the prize's `prize_type`
43
+ (`MiniGamePrizeTypeName`) to decide UI treatment:
44
+ - `'no-prize'` — the user spun but won nothing (an operator-
45
+ configured "loss" slot). Buy-in is still deducted.
46
+ - `'points'` / `'gems-and-diamonds'` / `'spin'` — value
47
+ credited to the user's profile / spin balance; visible on
48
+ the next refresh.
49
+ - `'bonus'` — surfaces via `getBonuses`.
50
+ - `'jackpot'` — drains the template's `jackpot_current` to the
51
+ user; resets the accumulator.
52
+ - `'raffle-ticket'` — adds tickets to the relevant raffle.
53
+ - `'mission'` / `'change-level'` — visible via the
54
+ corresponding domain methods.
55
+ - `'manual'` — operator delivers offline.
56
+
57
+ **Acknowledge** (the `acknowledge` parameter, default `true`)
58
+ Every spin is finalised by a follow-up acknowledge step that
59
+ marks the win delivered. By default the SDK sends that
60
+ acknowledge and AWAITS it, so `playMiniGame` resolves only after
61
+ the win is finalised server-side. Keep the default unless you
62
+ have a specific reason not to.
63
+
64
+ Pass `acknowledge: false` to skip that automatic step.
65
+ `playMiniGame` then resolves as soon as the spin result is known,
66
+ without waiting for the win to be marked delivered. You finalise
67
+ it later by calling `miniGameWinAcknowledgeRequest` with the
68
+ `request_id` returned on this result.
69
+
70
+ What `acknowledge: false` does and does NOT defer:
71
+ - For STANDARD prizes the value is credited at spin time
72
+ regardless, so opting out does NOT delay the balance change —
73
+ it only defers the "delivered" bookkeeping and the `is_claimed`
74
+ flag flipping in `getMiniGamesHistory`.
75
+ - For operator-configured "explicit claim" prizes the credit IS
76
+ deferred until the spin is acknowledged, so those require an
77
+ explicit acknowledge to finalise.
78
+
79
+ A server-side fallback auto-acknowledges ordinary un-acknowledged
80
+ spins after a short delay (about 1–3 minutes), so an ordinary
81
+ prize is never lost even without consumer action. "Explicit
82
+ claim" prizes are excluded from that fallback — if you use
83
+ `acknowledge: false` for one, you MUST acknowledge it explicitly
84
+ or its prize is never credited.
85
+
86
+ **Idempotency**: NOT idempotent. A double-click sends two
87
+ spins and deducts the buy-in twice. The SDK does NOT guard
88
+ against rapid clicks at the public API level — guard the call
89
+ site with an in-flight flag. The server enforces a per-user
90
+ per-template lock that serialises concurrent requests, so two
91
+ simultaneous calls won't be processed in parallel, but they
92
+ will both be processed sequentially (i.e. both deduct).
93
+
94
+ **Refresh after success (and after failure)**
95
+ The SDK automatically refreshes the templates cache on every
96
+ spin response and fires any `onUpdate` callback registered via
97
+ `getMiniGames` or this method. After `err_code === 0`, the
98
+ affected template's `spin_count` / `jackpot_current` /
99
+ `next_available_spin_ts` reflect the new state on the
100
+ refreshed array.
101
+
102
+ **Side effects** (on `err_code === 0`)
103
+ - Buy-in deducted at spin time (points / gems / diamonds / spin
104
+ tickets — depending on `saw_buyin_type`), already applied by the
105
+ time the call resolves. Balance updates flow via the
106
+ user-properties channel (observe via `getUserProfile`).
107
+ - Prize value credited per the prize's type (see "Prize handling"
108
+ above). Standard prizes are credited at spin time; "explicit
109
+ claim" prizes are credited when the spin is acknowledged.
110
+ - The play is recorded server-side for analytics / reporting.
111
+
112
+ **UI guidance**: see [UI Guide — `playMiniGame`](../../docs/ui/minigames/UIGuide_playMiniGame.md).
113
+
114
+ **Visitor mode**: not supported. Visitor sessions trying to
115
+ spin receive `SAW_VISITOR_STOP_SPIN_REQUEST (-40001)`.
116
+
117
+ ## Example
118
+ ```ts
119
+ const games = await window._smartico.api.getMiniGames({
120
+ onUpdate: (refreshed) => console.log('[smartico] templates refreshed — re-render lobby', refreshed),
121
+ });
122
+ const game = games.find(g => g.id === templateId);
123
+
124
+ if (!game) {
125
+ console.log('[smartico] template not in current list — refresh getMiniGames');
126
+ return;
127
+ }
128
+ if (game.saw_buyin_type === 'spins' && (game.spin_count ?? 0) === 0) {
129
+ console.log('[smartico] no spins available — disable Play button, show "No spins" message');
130
+ return;
131
+ }
132
+
133
+ console.log('[smartico] play starting — set in-flight flag, start game animation (wheel spin / scratch / lootbox open / etc.)');
134
+ const r = await window._smartico.api.playMiniGame(game.id);
135
+ console.log('[smartico] play response received');
136
+
137
+ if (r.err_code === 0) {
138
+ const prize = game.prizes.find(p => p.id === r.prize_id);
139
+ if (prize?.prize_type === 'no-prize') {
140
+ console.log('[smartico] user lost — animate to the no-prize slot and show "Better luck next time" modal');
141
+ } else {
142
+ console.log('[smartico] user won — animate to prize', prize?.name,
143
+ '— show acknowledge modal per template.acknowledge_type;',
144
+ 'getMiniGames onUpdate fires shortly with refreshed spin_count / jackpot');
145
+ }
146
+ } else if (r.err_code === 40004) {
147
+ console.error('[smartico] max spins reached — show countdown to next available spin (use playMiniGameBatch for first_spin_in_period if needed)');
148
+ } else if (r.err_code === -40001) {
149
+ console.log('[smartico] visitor stopped — silently end the game, no prize modal');
150
+ } else {
151
+ console.error('[smartico] play failed — show generic error with this message:', r.err_message);
152
+ }
153
+ ```
154
+
155
+ Manual finalisation (`acknowledge: false`) — e.g. an explicit
156
+ "Claim" CTA, or finalising on your own schedule:
157
+ ```ts
158
+ const r = await window._smartico.api.playMiniGame(game.id, { acknowledge: false });
159
+ if (r.err_code === 0) {
160
+ // Spin resolved but not yet acknowledged. For standard prizes the
161
+ // balance already changed server-side; "explicit claim" prizes
162
+ // are credited only by the acknowledge below.
163
+ console.log('[smartico] prize won — show the result / Claim CTA, then finalise');
164
+
165
+ // On the user's Claim click, finalise with the request_id from the result.
166
+ await window._smartico.api.miniGameWinAcknowledgeRequest(r.request_id);
167
+ console.log('[smartico] win finalised — refresh getUserProfile / getMiniGames to reflect it');
168
+ }
169
+ ```
170
+
171
+ ### Example response (REAL shape)
172
+ > Where this real payload differs from the typed Returns above (TS interface vs raw wire), the REAL shape is the runtime truth.
173
+ ```json
174
+ {
175
+ "err_code": 0,
176
+ "err_message": "",
177
+ "prize_id": 37373,
178
+ "request_id": "00000000-0000-0000-0000-000000000000"
179
+ }
180
+ ```
181
+
182
+ ## Errors
183
+ **Error codes** (in `err_code`, typed as `SAWSpinErrorCode`)
184
+ - `0` (`SAW_OK`) — success; `prize_id` identifies the won prize
185
+ in `template.prizes`.
186
+ - `40001` (`SAW_NO_SPINS`) — user has no spin attempts for a
187
+ spin-based template.
188
+ - `40002` (`SAW_PRIZE_POOL_EMPTY`) — all prize slots in the
189
+ template are depleted.
190
+ - `40003` (`SAW_NOT_ENOUGH_POINTS`) — insufficient points for a
191
+ points-cost template.
192
+ - `40004` (`SAW_FAILED_MAX_SPINS_REACHED`) — per-period
193
+ max-attempts cap reached. The server's
194
+ `first_spin_in_period` value (exposed in
195
+ `TMiniGamePlayBatchResult`; not surfaced in the single
196
+ `TMiniGamePlayResult`) marks the period start.
197
+ - `40007` (`SAW_TEMPLATE_NOT_ACTIVE`) — template outside its
198
+ active time window.
199
+ - `40009` (`SAW_NOT_IN_SEGMENT`) — user fails the template's
200
+ visibility segment check, OR (for lootbox variants) the day's
201
+ prize pool is empty.
202
+ - `40011` (`SAW_NO_BALANCE_GEMS`) — insufficient gems.
203
+ - `40012` (`SAW_NO_BALANCE_DIAMONDS`) — insufficient diamonds.
204
+ - `-40001` (`SAW_VISITOR_STOP_SPIN_REQUEST`) — visitor session
205
+ tried to play a non-visitor-mode template. The default UI
206
+ silently stops the game; no prize awarded.
207
+ - other non-zero — generic server error. Surface `err_message`.
208
+
209
+ ## Related
210
+ - `getMiniGames`
211
+ - `getUserProfile`
212
+ - `SAWSpinErrorCode`
213
+ - `TMiniGamePlayBatchResult`
214
+ - `MiniGamePrizeTypeName`
215
+ - `getBonuses`
216
+ - `miniGameWinAcknowledgeRequest`
217
+ - `getMiniGamesHistory`
@@ -0,0 +1,129 @@
1
+ # playMiniGameBatch — API (TMiniGamePlayBatchResult)
2
+
3
+ > Plays a mini-game template `spin_count` times in one round-trip.
4
+ > Import: `import { TMiniGamePlayBatchResult } from '@smartico/public-api'`
5
+ > Search terms: playMiniGameBatch, minigames, doSAWSpinBatch, TMiniGamePlayBatchResult, SAWSpinErrorCode, onUpdate, subscription, errCode, errMessage, saw_prize_id, jackpot_amount, first_spin_in_period
6
+
7
+ ## Signature
8
+ ```ts
9
+ _smartico.api.playMiniGameBatch(template_id: number, spin_count: number, { onUpdate }: { onUpdate?: (data: TMiniGameTemplate[]) => void } = {}): Promise<TMiniGamePlayBatchResult[]>
10
+ ```
11
+
12
+ ## Parameters
13
+ - `template_id` — The mini-game template ID.
14
+ - `spin_count` — Number of spins to play. The server attempts all `spin_count` spins — partial successes are normal when the user runs out of balance / spins mid-batch.
15
+ - `params` — Optional. Pass an `onUpdate` callback to subscribe to subsequent template refreshes.
16
+
17
+ ## Returns — `Promise<TMiniGamePlayBatchResult[]>`
18
+ Array of `TMiniGamePlayBatchResult`. Each item:
19
+ - `saw_prize_id` (number) — ID of the won prize for this spin. Look up in `template.prizes`.
20
+ - `errCode` (SAWSpinErrorCode) — Error code. `0` = success. See `playMiniGameBatch` TSDoc for the full table.
21
+ - `errMessage` (string) — Optional server-side error message.
22
+ - `jackpot_amount` (number) — Jackpot amount the user won, populated when the prize type is `'jackpot'`.
23
+ - `first_spin_in_period` (number) — Epoch ms of the user's first spin in the current cooldown period; populated when `errCode === SAWSpinErrorCode.SAW_FAILED_MAX_SPINS_REACHED`.
24
+
25
+ ## Behavioral contract
26
+ **Result shape note** — `TMiniGamePlayBatchResult` uses
27
+ `errCode` / `errMessage` (camelCase) — DIFFERENT from
28
+ `TMiniGamePlayResult` which uses `err_code` / `err_message`
29
+ (snake_case). Branch on the camelCase keys when reading batch
30
+ results.
31
+
32
+ **Per-spin independence**
33
+ The server iterates the requested spins and calls the prize
34
+ engine once per entry. If spin #2 fails with `SAW_NO_SPINS`,
35
+ spin #3 is still attempted — the server does NOT stop on first
36
+ error and does NOT roll back successful spins. Each
37
+ `results[i].errCode` is independent.
38
+
39
+ Practical implication: if the user has 3 spins available and
40
+ requests 5, expect results 0-2 with `errCode === 0` and results
41
+ 3-4 with `errCode === SAW_NO_SPINS`.
42
+
43
+
44
+
45
+ **Auto-acknowledge**
46
+ The SDK fires a batch-acknowledge for all `request_id`s after
47
+ the batch response lands — fire-and-forget. Same recovery
48
+ semantics as `playMiniGame`: lost acknowledgements
49
+ become recoverable via `miniGameWinAcknowledgeRequest`
50
+ per row, and a server-side fallback job auto-acknowledges
51
+ stale spins every ~60 seconds.
52
+
53
+ **Idempotency**: NOT idempotent. A double-click sends two
54
+ batches. Guard the call site with an in-flight flag.
55
+
56
+ **Refresh after success (and after failure)**
57
+ Same as `playMiniGame` — the templates cache refreshes
58
+ and any `onUpdate` callback registered via `getMiniGames`
59
+ fires with the updated `spin_count` / `jackpot_current`.
60
+
61
+ **Side effects** (per-spin, on `errCode === 0`)
62
+ Same as `playMiniGame` — buy-in deducted, prize value
63
+ credited per prize type.
64
+
65
+ **UI guidance**: see [UI Guide — `playMiniGameBatch`](../../docs/ui/minigames/UIGuide_playMiniGameBatch.md).
66
+
67
+ **Visitor mode**: not supported.
68
+
69
+ ## Example
70
+ ```ts
71
+ const game = (await window._smartico.api.getMiniGames()).find(g => g.id === templateId);
72
+ if (!game) return;
73
+
74
+ console.log('[smartico] batch play starting — set in-flight flag, animate the chosen N spins sequentially in UI');
75
+ const results = await window._smartico.api.playMiniGameBatch(game.id, 5);
76
+ console.log('[smartico] batch response received — clear in-flight flag');
77
+
78
+ for (const [i, r] of results.entries()) {
79
+ if (r.errCode === 0) {
80
+ const prize = game.prizes.find(p => p.id === r.saw_prize_id);
81
+ console.log('[smartico] spin', i, 'won:', prize?.name,
82
+ r.jackpot_amount ? '(jackpot: ' + r.jackpot_amount + ')' : '');
83
+ } else if (r.errCode === 40004) {
84
+ const msTillNext = game.max_spins_period_ms! - (Date.now() - (r.first_spin_in_period ?? 0));
85
+ console.log('[smartico] spin', i, 'capped — ' + Math.ceil(msTillNext / 1000) + ' s until next allowed');
86
+ } else {
87
+ console.error('[smartico] spin', i, 'failed —', r.errCode, r.errMessage);
88
+ }
89
+ }
90
+ ```
91
+
92
+ ### Example response (REAL shape)
93
+ > Where this real payload differs from the typed Returns above (TS interface vs raw wire), the REAL shape is the runtime truth.
94
+ ```json
95
+ [
96
+ {
97
+ "errCode": 40004,
98
+ "errMessage": "Failed to spin. Max spins reached",
99
+ "saw_prize_id": null,
100
+ "jackpot_amount": null,
101
+ "first_spin_in_period": 1782287011000
102
+ }
103
+ ]
104
+ ```
105
+
106
+ ## Errors
107
+ **Error codes**
108
+ Per-result `errCode` is from `SAWSpinErrorCode`. See
109
+ `playMiniGame` for the full table; the same codes apply
110
+ per spin.
111
+
112
+ **`first_spin_in_period` field**
113
+ Populated on results where `errCode === SAW_FAILED_MAX_SPINS_REACHED`
114
+ (40004). The value is the epoch-ms timestamp of the user's
115
+ first spin in the current cooldown period. Compute the
116
+ countdown as:
117
+ `template.max_spins_period_ms - (Date.now() - first_spin_in_period)`.
118
+
119
+ **`jackpot_amount` field**
120
+ Populated on results where the won prize is a jackpot
121
+ (`prize_type === 'jackpot'`). The amount the user just claimed
122
+ from the template's jackpot accumulator.
123
+
124
+ ## Related
125
+ - `playMiniGame`
126
+ - `TMiniGamePlayResult`
127
+ - `SAWSpinErrorCode`
128
+ - `miniGameWinAcknowledgeRequest`
129
+ - `getMiniGames`
@@ -0,0 +1,187 @@
1
+ # registerInTournament — API (TTournamentRegistrationResult)
2
+
3
+ > Registers the authenticated user in the specified tournament instance.
4
+ > Import: `import { TTournamentRegistrationResult } from '@smartico/public-api'`
5
+ > Search terms: registerInTournament, tournaments, TTournamentRegistrationResult, TournamentRegistrationError, err_code, err_message
6
+
7
+ ## Signature
8
+ ```ts
9
+ _smartico.api.registerInTournament(tournamentInstanceId: number): Promise<TTournamentRegistrationResult>
10
+ ```
11
+
12
+ ## Parameters
13
+ - `tournamentInstanceId` — The `instance_id` from `TTournament` (NOT the template `tournament_id`).
14
+
15
+ ## Returns — `Promise<TTournamentRegistrationResult>`
16
+ `TTournamentRegistrationResult`:
17
+ - `err_code` (TournamentRegistrationError) — Error code. `0` = success. See `registerInTournament` TSDoc for the full table.
18
+ - `err_message` (string) — Optional error message; populated on non-zero `err_code`.
19
+
20
+ ## Behavioral contract
21
+ **Preconditions**
22
+ Read the candidate from `getTournamentsList` and gate the call
23
+ on `is_can_register === true`. This composite flag already encodes:
24
+ not already registered, slot available
25
+ (`registration_count < players_max_count`), tournament status is
26
+ REGISTER (or STARTED with late-registration enabled), and the
27
+ registration type is not AUTO. The SDK forwards the call
28
+ unconditionally — calling without satisfying these will return one
29
+ of the error codes below.
30
+
31
+ For clan tournaments (`is_clan_based === true`), the user must
32
+ already belong to a clan before calling. If they don't, prompt them
33
+ to pick a clan first via `joinClan`, then call
34
+ `registerInTournament` after the clan-join resolves. See "Error
35
+ codes" `1010` below for the server-side safety net.
36
+
37
+
38
+
39
+ **Idempotency**: NOT idempotent. A second call on the same instance
40
+ returns `30004` once the first call has succeeded. The SDK does NOT
41
+ enforce an in-flight lock. The consumer MUST guard the call site
42
+ against double-clicks (set a local "registering" flag on click, clear
43
+ it on response).
44
+
45
+ **Refresh after success (and after failure)**
46
+ The SDK automatically refreshes the tournament lobby cache on every
47
+ response (success OR error) and fires any `onUpdate` callback
48
+ registered via `getTournamentsList({ onUpdate })`. After
49
+ `err_code === 0`, the affected item's `is_user_registered` /
50
+ `registration_status` / `registration_count` reflect the new
51
+ registered state on the refreshed array. Note that
52
+ `getTournamentInstanceInfo` is NOT auto-refreshed — if the
53
+ detail screen is open, call it again manually.
54
+
55
+ The user's balance (points / gems / diamonds) is exposed on the
56
+ user-properties channel and updates independently of this call's
57
+ response — subscribe to user-property updates separately if your UI
58
+ shows the balance.
59
+
60
+ **Side effects** (consumer-observable on success)
61
+ - Balance debited synchronously by the buy-in amount in the
62
+ tournament's currency (`registration_cost_points`,
63
+ `registration_cost_gems`, or `registration_cost_diamonds`). For
64
+ free tournaments no deduction occurs.
65
+ - Server-side analytics events fire downstream
66
+ (`tournament_user_registered` for immediate-registration types;
67
+ `tournament_user_registration_pending` or
68
+ `tournament_registered_pending_qualification` for
69
+ manual-approval / qualification-based types).
70
+ - Any operator-configured on-join prizes are distributed (e.g.
71
+ welcome bonus). These surface via the relevant follow-up channels
72
+ (e.g. `getBonuses`).
73
+
74
+ **UI guidance**: see [UI Guide — `registerInTournament`](../../docs/ui/tournaments/UIGuide_registerInTournament.md).
75
+
76
+ **Visitor mode**: not supported. Calling from a visitor session
77
+ returns a generic error, not a typed `TournamentRegistrationError`.
78
+
79
+ ## Example
80
+ ```ts
81
+ const tournaments = await window._smartico.api.getTournamentsList({
82
+ onUpdate: (refreshed) => console.log('[smartico] tournament list updated — re-render lobby from this array', refreshed),
83
+ });
84
+ const tournament = tournaments.find(t => t.instance_id === instanceId);
85
+
86
+ if (!tournament) {
87
+ console.log('[smartico] tournament not in current lobby — refresh getTournamentsList and retry');
88
+ return;
89
+ }
90
+ if (!tournament.is_can_register) {
91
+ console.log('[smartico] tournament not currently registerable — keep CTA disabled');
92
+ return;
93
+ }
94
+
95
+ // Clan tournament + user has no clan → resolve clan first.
96
+ if (tournament.is_clan_based) {
97
+ const userProfile = window._smartico.api.getUserProfile();
98
+ const userClanId = userProfile?.clan_id;
99
+ if (userClanId == null) {
100
+ console.log('[smartico] clan tournament — open the clan-pick modal first; after joinClan resolves, call registerInTournament again');
101
+ return;
102
+ }
103
+ }
104
+
105
+ console.log('[smartico] registration starting — set in-flight flag, show loading dots on the Join button, keep modal open');
106
+ const r = await window._smartico.api.registerInTournament(tournament.instance_id);
107
+ console.log('[smartico] registration response received — clear in-flight flag');
108
+
109
+ if (r.err_code === 0 || r.err_code === 30004) {
110
+ console.log('[smartico] registered (or was already) — close any modal, show a success toast; getTournamentsList onUpdate above will fire with the refreshed array');
111
+ } else if (r.err_code === 1010) {
112
+ console.log('[smartico] clan required — open the clan-pick modal again (this is the server-side safety net for a clan-leave race)');
113
+ } else if (r.err_code === 30002) {
114
+ console.error('[smartico] insufficient points — show insufficient-balance UI; deficit:', tournament.registration_cost_points);
115
+ } else if (r.err_code === 300010) {
116
+ console.error('[smartico] insufficient gems — show insufficient-balance UI; deficit:', tournament.registration_cost_gems);
117
+ } else if (r.err_code === 300011) {
118
+ console.error('[smartico] insufficient diamonds — show insufficient-balance UI; deficit:', tournament.registration_cost_diamonds);
119
+ } else if (r.err_code === 30005) {
120
+ console.error('[smartico] segment mismatch — prefer the operator-supplied message:', tournament.segment_dont_match_message || r.err_message);
121
+ } else if (r.err_code === 30008) {
122
+ console.error('[smartico] tournament full — auto-refresh will hide the button on the refreshed lobby item');
123
+ } else {
124
+ console.error('[smartico] registration failed — show a generic error toast with this message:', r.err_message);
125
+ }
126
+ ```
127
+
128
+ ### Example response (REAL shape)
129
+ > Where this real payload differs from the typed Returns above (TS interface vs raw wire), the REAL shape is the runtime truth.
130
+ ```json
131
+ {
132
+ "err_code": 0,
133
+ "err_message": ""
134
+ }
135
+ ```
136
+
137
+ ## Errors
138
+ **Error codes** (in `err_code`, typed as `TournamentRegistrationError`)
139
+ - `0` — success; the registration is persisted, buy-in deducted,
140
+ tournament lobby refresh fires.
141
+ - `1010` — `TOURNAMENT_USER_CANNOT_JOIN_WITHOUT_CLAN`: clan-based
142
+ tournament and the user has no clan. Surface the clan-pick flow
143
+ (e.g. open a clan-pick modal driven by `getClans` +
144
+ `joinClan`), then retry registration.
145
+ - `30001` — `TOURNAMENT_INSTANCE_NOT_FOUND`: instance ID is invalid
146
+ or the tournament was deleted. Refresh the lobby via
147
+ `getTournamentsList()` and hide the entry from the UI.
148
+ - `30002` — `TOURNAMENT_REGISTRATION_NOT_ENOUGH_POINTS`: insufficient
149
+ points balance for a points-cost tournament. Show an
150
+ insufficient-balance UI naming the deficit.
151
+ - `30003` — `TOURNAMENT_INSTANCE_NOT_IN_STATE`: tournament is no
152
+ longer in a registerable state (finished, cancelled, finalizing,
153
+ or not yet published with late registration disabled). Refresh
154
+ the lobby; the button should hide.
155
+ - `30004` — `TOURNAMENT_ALREADY_REGISTERED`: user is already
156
+ registered. Treat as idempotent success — hide the Register button
157
+ and refresh the lobby. Usually indicates a stale local state
158
+ (e.g. registered from another tab).
159
+ - `30005` — `TOURNAMENT_USER_DONT_MATCH_CONDITIONS`: user fails the
160
+ tournament's segment / entry conditions. Prefer
161
+ `tournament.segment_dont_match_message` (operator-supplied) over
162
+ `err_message` when both are available.
163
+ - `30006` — `TOURNAMENT_USER_NOT_REGISTERED`: anomalous on a fresh
164
+ register call; usually indicates a server-side race. Treat as a
165
+ generic transient error.
166
+ - `30007` — `TOURNAMENT_CANT_CHANGE_REGISTRATION_STATUS`: status
167
+ transition not allowed (e.g. re-registering after a finished /
168
+ cancelled tournament). Show a generic error; do not retry.
169
+ - `30008` — `TOURNAMENT_MAX_REGISTRATIONS_REACHED`: the tournament
170
+ filled up between the lobby fetch and the registration click.
171
+ Refresh the lobby — the button will hide on the refreshed item.
172
+ - `300010` — insufficient **gems** balance (gems-cost tournament).
173
+ Same UI handling as `30002` but for the gems currency.
174
+ - `300011` — insufficient **diamonds** balance (diamonds-cost
175
+ tournament). Same as `300010` but for diamonds.
176
+ - other non-zero — generic server error. Surface `err_message` if any.
177
+
178
+ Note: clan-tournament registration can occasionally surface error
179
+ codes from the clan-join domain (e.g. `1011` — joined-after-start)
180
+ via the same response path. These are members of `JoinClanErrorCode`,
181
+ not `TournamentRegistrationError`. Branch on the numeric value.
182
+
183
+ ## Related
184
+ - `getTournamentsList`
185
+ - `TournamentRegistrationError`
186
+ - `getTournamentInstanceInfo`
187
+ - `getBonuses`
@@ -0,0 +1,74 @@
1
+ # reportClickEvent — API
2
+
3
+ > Records that the user interacted with an engagement — typically tapping a CTA button, following a deep-link, or clicking a popup action.
4
+ > Import: `import { /* types */ } from '@smartico/public-api'`
5
+ > Search terms: reportClickEvent, inbox
6
+
7
+ ## Signature
8
+ ```ts
9
+ _smartico.api.reportClickEvent({
10
+ engagement_uid,
11
+ activityType,
12
+ action,
13
+ }: {
14
+ /** For inbox: the message's `message_guid` from `getInboxMessages`. */
15
+ engagement_uid: string;
16
+ /** `ActivityTypeLimited.Inbox` (`31`) for inbox; `Popup` (`30`) for popups. */
17
+ activityType: ActivityTypeLimited | number;
18
+ /** The deep-link / URL the user triggered (optional but recommended for analytics fidelity). */
19
+ action?: string;
20
+ }): void
21
+ ```
22
+
23
+ ## Parameters
24
+ _None._
25
+
26
+ ## Returns
27
+ _No return value._
28
+
29
+ ## Behavioral contract
30
+ **When to call**
31
+ - Inbox: when the user taps a CTA button on a message or follows
32
+ a deep-link inside the message body. Pass the deep-link or URL
33
+ as `action`.
34
+ - Popup: when the user clicks a popup action button.
35
+
36
+ **Activity types**
37
+ Pass `ActivityTypeLimited.Inbox` (`31`) for inbox,
38
+ `ActivityTypeLimited.Popup` (`30`) for popups.
39
+
40
+ **`action` payload**
41
+ Pass the deep-link or URL that the user triggered (e.g.
42
+ `'dp:gf_missions'`, `'https://example.com/promo'`). The SDK
43
+ forwards the string to the server for analytics — it does not
44
+ execute the deep-link. To execute deep-links safely, call
45
+ `_smartico.dp(action)` separately.
46
+
47
+ **Idempotency**: the server records every click event —
48
+ repeated calls add to the count. Fire once per logical user
49
+ action.
50
+
51
+ **Side effects**: server-side updates the engagement's
52
+ `last_action` field; observable via operator analytics. The SDK
53
+ consumer receives no signal back.
54
+
55
+ **Visitor mode**: not supported.
56
+
57
+ ## Example
58
+ ```ts
59
+ // When the user taps a CTA button in an inbox message.
60
+ window._smartico.api.reportClickEvent({
61
+ engagement_uid: message.message_guid,
62
+ activityType: 31, // ActivityTypeLimited.Inbox
63
+ action: 'dp:gf_missions',
64
+ });
65
+ window._smartico.dp('dp:gf_missions'); // separately execute the deep-link
66
+ ```
67
+
68
+ ## Errors
69
+ See this method's TSDoc / the mutation pages for `err_code` handling.
70
+
71
+ ## Related
72
+ - `reportImpressionEvent`
73
+ - `ActivityTypeLimited.Inbox`
74
+ - `ActivityTypeLimited.Popup`
@@ -0,0 +1,67 @@
1
+ # reportImpressionEvent — API
2
+
3
+ > Records that an engagement (inbox message, popup) was displayed to the user.
4
+ > Import: `import { /* types */ } from '@smartico/public-api'`
5
+ > Search terms: reportImpressionEvent, inbox
6
+
7
+ ## Signature
8
+ ```ts
9
+ _smartico.api.reportImpressionEvent({
10
+ engagement_uid,
11
+ activityType,
12
+ }: {
13
+ /** For inbox: the message's `message_guid` from `getInboxMessages`. For popups: the popup's GUID from the popup display callback. */
14
+ engagement_uid: string;
15
+ /** `ActivityTypeLimited.Inbox` (`31`) for inbox; `Popup` (`30`) for popups. */
16
+ activityType: ActivityTypeLimited | number;
17
+ }): void
18
+ ```
19
+
20
+ ## Parameters
21
+ _None._
22
+
23
+ ## Returns
24
+ _No return value._
25
+
26
+ ## Behavioral contract
27
+ **When to call**
28
+ - Inbox: when a message becomes visible (the user opens / scrolls
29
+ it into view). The default Smartico UI fires this when the
30
+ message detail expands, alongside
31
+ `markInboxMessageAsRead`.
32
+ - Popup: when the popup content is shown to the user.
33
+
34
+ **Activity types**
35
+ Pass `ActivityTypeLimited.Inbox` (`31`) for inbox messages,
36
+ `ActivityTypeLimited.Popup` (`30`) for popups. Other values
37
+ are not used by the engagement-impression channel.
38
+
39
+ **Idempotency**: the server records every impression event —
40
+ repeated calls add to the impression count. Don't fire it on
41
+ every re-render; fire it once per logical "display" event
42
+ (modal open, list-row scroll-into-view, popup show).
43
+
44
+ **Side effects**: server-side increments the engagement's
45
+ `impression_count` and updates `last_impression_date`. The
46
+ counter is observable via operator analytics; the SDK consumer
47
+ receives no signal back.
48
+
49
+ **Visitor mode**: not supported.
50
+
51
+ ## Example
52
+ ```ts
53
+ // When the user opens an inbox message in the detail view.
54
+ window._smartico.api.reportImpressionEvent({
55
+ engagement_uid: message.message_guid,
56
+ activityType: 31, // ActivityTypeLimited.Inbox
57
+ });
58
+ console.log('[smartico] inbox impression reported for', message.message_guid, '— no response to await, fire-and-forget');
59
+ ```
60
+
61
+ ## Errors
62
+ See this method's TSDoc / the mutation pages for `err_code` handling.
63
+
64
+ ## Related
65
+ - `markInboxMessageAsRead`
66
+ - `ActivityTypeLimited.Inbox`
67
+ - `ActivityTypeLimited.Popup`