@fundedfast/sdk 1.3.0 → 1.4.0
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.
- package/CHANGELOG.md +128 -0
- package/README.md +8 -8
- package/dist/cjs/client.d.ts +3 -1
- package/dist/cjs/client.d.ts.map +1 -1
- package/dist/cjs/client.js +19 -2
- package/dist/cjs/client.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/resources/admin.d.ts +285 -84
- package/dist/cjs/resources/admin.d.ts.map +1 -1
- package/dist/cjs/resources/admin.js +326 -99
- package/dist/cjs/resources/admin.js.map +1 -1
- package/dist/cjs/resources/public.d.ts +44 -17
- package/dist/cjs/resources/public.d.ts.map +1 -1
- package/dist/cjs/resources/public.js +80 -35
- package/dist/cjs/resources/public.js.map +1 -1
- package/dist/cjs/types.d.ts +662 -81
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/esm/client.d.ts +3 -1
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +19 -2
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/resources/admin.d.ts +285 -84
- package/dist/esm/resources/admin.d.ts.map +1 -1
- package/dist/esm/resources/admin.js +324 -98
- package/dist/esm/resources/admin.js.map +1 -1
- package/dist/esm/resources/public.d.ts +44 -17
- package/dist/esm/resources/public.d.ts.map +1 -1
- package/dist/esm/resources/public.js +80 -35
- package/dist/esm/resources/public.js.map +1 -1
- package/dist/esm/types.d.ts +662 -81
- package/dist/esm/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/esm/types.d.ts
CHANGED
|
@@ -21,9 +21,17 @@ export type WebhookDeliveryStatus = 'pending' | 'delivered' | 'failed';
|
|
|
21
21
|
/** Tenant integration mode */
|
|
22
22
|
export type IntegrationMode = 'sync' | 'async';
|
|
23
23
|
/** All possible rejection reason codes from the rules engine */
|
|
24
|
-
export type RejectionCode = 'min_stake_not_met' | 'max_stake_exceeded' | 'odds_limit_exceeded' | 'min_odds_not_met' | 'max_payout_exceeded' | 'max_selections_exceeded' | 'max_win_exceeded' | 'lucky_bet_profit_limit' | 'daily_drawdown_exceeded' | 'max_drawdown_exceeded' | 'cooldown_active' | 'cashout_not_allowed_during_challenge'
|
|
24
|
+
export type RejectionCode = 'min_stake_not_met' | 'max_stake_exceeded' | 'odds_limit_exceeded' | 'min_odds_not_met' | 'max_payout_exceeded' | 'max_selections_exceeded' | 'max_win_exceeded' | 'lucky_bet_profit_limit' | 'daily_drawdown_exceeded' | 'max_drawdown_exceeded' | 'cooldown_active' | 'payout_pending' | 'cashout_not_allowed_during_challenge'
|
|
25
|
+
/** Settlements only. A won/lost after a different result for the same bet: held for an operator, no balance change. */
|
|
26
|
+
| 'conflicting_settlement'
|
|
27
|
+
/** Settlements only. Stake or odds differ from the accepted placement, or the payout exceeds stake x odds: held, no balance change. */
|
|
28
|
+
| 'settlement_mismatch'
|
|
29
|
+
/** Settlements only. FAST never accepted this bet (rejected, or placed with no programme). Recorded, no balance change. */
|
|
30
|
+
| 'no_accepted_placement'
|
|
31
|
+
/** Settlements only. Accepted on a programme that has closed since, typically a challenge that passed with the bet still open. Recorded under that programme, no balance change. */
|
|
32
|
+
| 'program_closed';
|
|
25
33
|
/** Webhook event types emitted by FAST */
|
|
26
|
-
export type WebhookEventType = 'challenge.activated' | 'challenge.passed' | 'challenge.completed' | 'challenge.failed' | 'challenge.cancelled' | 'challenge.expiring_soon' | 'challenge.stake_refunded' | 'challenge.bonus_voided' | 'funded_account.activated' | 'funded_account.revoked' | 'funded_account.payout' | 'funded_account.stake_refunded' | 'cooldown.triggered' | 'cooldown.lifted' | 'bet.validation_result' | 'achievement.earned' | 'reward.granted' | 'reward.applied' | 'user.self_excluded' | 'user.self_exclusion_lifted' | 'bonus.activated' | 'bonus.progress' | 'bonus.completed' | 'bonus.expired' | 'bonus.forfeited' | 'mission.enrolled' | 'mission.progress' | 'mission.completed' | 'mission.expired' | 'tournament.started' | 'tournament.user_joined' | 'tournament.user_invited' | 'tournament.settled' | 'tournament.cancelled' | 'loyalty.tier_upgraded' | 'loyalty.tier_downgraded' | 'loyalty.cashback_settled' | 'reward.expired';
|
|
34
|
+
export type WebhookEventType = 'challenge.activated' | 'challenge.passed' | 'challenge.completed' | 'challenge.failed' | 'challenge.cancelled' | 'challenge.expiring_soon' | 'challenge.stake_refunded' | 'challenge.bonus_voided' | 'funded_account.activated' | 'funded_account.revoked' | 'funded_account.payout' | 'funded_account.stake_refunded' | 'funded_account.payout_requested' | 'funded_account.payout_rejected' | 'cooldown.triggered' | 'cooldown.lifted' | 'bet.validation_result' | 'achievement.earned' | 'reward.granted' | 'reward.applied' | 'user.self_excluded' | 'user.self_exclusion_lifted' | 'bonus.activated' | 'bonus.progress' | 'bonus.completed' | 'bonus.expired' | 'bonus.forfeited' | 'mission.enrolled' | 'mission.progress' | 'mission.completed' | 'mission.expired' | 'tournament.started' | 'tournament.user_joined' | 'tournament.user_invited' | 'tournament.settled' | 'tournament.cancelled' | 'loyalty.tier_upgraded' | 'loyalty.tier_downgraded' | 'loyalty.cashback_settled' | 'reward.expired';
|
|
27
35
|
/** Body for POST /challenges/purchase */
|
|
28
36
|
export interface PurchaseRequest {
|
|
29
37
|
/** Your sportsbook user identifier */
|
|
@@ -60,8 +68,91 @@ export interface BetEvent {
|
|
|
60
68
|
}
|
|
61
69
|
/** Body for POST /users/:userId/withdraw */
|
|
62
70
|
export interface WithdrawRequest {
|
|
63
|
-
/** Amount to
|
|
71
|
+
/** Amount to pay out. Must be <= withdrawable and >= the minimum payout. Ignored on the last allowed payout, which is always the full available amount. */
|
|
72
|
+
amount?: number;
|
|
73
|
+
/** Leave the request pending for a later confirm/reject instead of executing it now. */
|
|
74
|
+
deferred?: boolean;
|
|
75
|
+
}
|
|
76
|
+
/** Why a payout is not possible yet. Every reason that applies is listed. */
|
|
77
|
+
export interface PayoutReason {
|
|
78
|
+
code: 'account_not_active' | 'payout_pending' | 'max_payouts_reached' | 'no_profit' | 'insufficient_active_days' | 'insufficient_bets' | 'below_min_payout' | 'payout_interval' | 'open_bets';
|
|
79
|
+
/** False when the reason only keeps the cycle share out and unpaid profit can still be requested. */
|
|
80
|
+
blocking: boolean;
|
|
81
|
+
current?: number;
|
|
82
|
+
required?: number;
|
|
83
|
+
missing?: number;
|
|
84
|
+
until?: string;
|
|
85
|
+
}
|
|
86
|
+
export interface PendingPayout {
|
|
87
|
+
id: string;
|
|
88
|
+
amount: number;
|
|
89
|
+
fromUnpaid: number;
|
|
90
|
+
fromCycle: number;
|
|
91
|
+
isFinal: boolean;
|
|
92
|
+
isMandatory: boolean;
|
|
93
|
+
createdAt: string;
|
|
94
|
+
}
|
|
95
|
+
/** Payout state of a funded account (the per-cycle model). */
|
|
96
|
+
export interface PayoutState {
|
|
97
|
+
currentBalance: number;
|
|
98
|
+
fundedAmount: number;
|
|
99
|
+
profitSplitPercent: number;
|
|
100
|
+
cycleProfit: number;
|
|
101
|
+
cycleShare: number;
|
|
102
|
+
/** Already split, not yet paid. Not part of the balance, never split again. */
|
|
103
|
+
unpaidProfit: number;
|
|
104
|
+
available: number;
|
|
105
|
+
withdrawableNow: number;
|
|
106
|
+
activeDays: number;
|
|
107
|
+
minActiveDays: number;
|
|
108
|
+
cycleBets: number;
|
|
109
|
+
minBets: number;
|
|
110
|
+
conditionsMet: boolean;
|
|
111
|
+
payoutCount: number;
|
|
112
|
+
maxPayouts: number | null;
|
|
113
|
+
remainingPayouts: number | null;
|
|
114
|
+
isFinal: boolean;
|
|
115
|
+
minPayout: number | null;
|
|
116
|
+
payoutIntervalDays: number | null;
|
|
117
|
+
lastPayoutAt: string | null;
|
|
118
|
+
nextPayoutAt: string | null;
|
|
119
|
+
mandatoryPayoutThreshold: number | null;
|
|
120
|
+
totalWithdrawn: number;
|
|
121
|
+
openStake: number;
|
|
122
|
+
pending: PendingPayout | null;
|
|
123
|
+
reasons: PayoutReason[];
|
|
124
|
+
canRequest: boolean;
|
|
125
|
+
}
|
|
126
|
+
export interface PayoutRequest {
|
|
127
|
+
id: string;
|
|
128
|
+
fundedAccountId: string;
|
|
129
|
+
userId: string;
|
|
64
130
|
amount: number;
|
|
131
|
+
fromUnpaid: number;
|
|
132
|
+
fromCycle: number;
|
|
133
|
+
isFinal: boolean;
|
|
134
|
+
isMandatory: boolean;
|
|
135
|
+
status: 'pending' | 'executed' | 'rejected';
|
|
136
|
+
rejectionReason: string | null;
|
|
137
|
+
ownStakeReturned: number | null;
|
|
138
|
+
decidedBy: string | null;
|
|
139
|
+
createdAt: string;
|
|
140
|
+
decidedAt: string | null;
|
|
141
|
+
}
|
|
142
|
+
/** A payout request as the user's own list returns it: who decided it is not included. */
|
|
143
|
+
export type UserPayoutRequest = Omit<PayoutRequest, 'decidedBy'>;
|
|
144
|
+
/** Result of confirming a payout request. */
|
|
145
|
+
export interface PayoutExecution {
|
|
146
|
+
payoutRequestId: string;
|
|
147
|
+
userPayout: number;
|
|
148
|
+
ownStakeReturned: number;
|
|
149
|
+
totalPayout: number;
|
|
150
|
+
operatorShare: number;
|
|
151
|
+
newBalance: number;
|
|
152
|
+
unpaidProfit: number;
|
|
153
|
+
cycleClosed: boolean;
|
|
154
|
+
forfeitedProfit: number;
|
|
155
|
+
accountClosed: boolean;
|
|
65
156
|
}
|
|
66
157
|
/** A challenge instance */
|
|
67
158
|
export interface Challenge {
|
|
@@ -88,6 +179,54 @@ export interface Challenge {
|
|
|
88
179
|
createdAt: string;
|
|
89
180
|
updatedAt: string;
|
|
90
181
|
}
|
|
182
|
+
/** A challenge as GET /users/:userId/history returns it. */
|
|
183
|
+
export interface ChallengeHistory {
|
|
184
|
+
id: string;
|
|
185
|
+
status: ChallengeStatus;
|
|
186
|
+
failureReason?: string | null;
|
|
187
|
+
ownStake: number;
|
|
188
|
+
startingBalance: number;
|
|
189
|
+
currentBalance: number;
|
|
190
|
+
targetBalance: number;
|
|
191
|
+
startedAt?: string | null;
|
|
192
|
+
expiresAt?: string | null;
|
|
193
|
+
totalBetsPlaced: number;
|
|
194
|
+
totalBetsAccepted: number;
|
|
195
|
+
activeDaysCount: number;
|
|
196
|
+
createdAt?: string | null;
|
|
197
|
+
/** Name of the tier it was bought as. */
|
|
198
|
+
tierName?: string | null;
|
|
199
|
+
/** When it finished. Null while active or awaiting the continue/refund choice. */
|
|
200
|
+
endedAt?: string | null;
|
|
201
|
+
}
|
|
202
|
+
/** A payout request as listed on a funded account in the user history. */
|
|
203
|
+
export interface HistoryPayout {
|
|
204
|
+
amount: number;
|
|
205
|
+
status: 'pending' | 'executed' | 'rejected';
|
|
206
|
+
isFinal: boolean;
|
|
207
|
+
isMandatory: boolean;
|
|
208
|
+
createdAt: string;
|
|
209
|
+
decidedAt?: string | null;
|
|
210
|
+
}
|
|
211
|
+
/** A funded account as GET /users/:userId/history returns it. */
|
|
212
|
+
export interface FundedAccountHistory {
|
|
213
|
+
id: string;
|
|
214
|
+
status: string;
|
|
215
|
+
revocationReason?: string | null;
|
|
216
|
+
fundedAmount: number;
|
|
217
|
+
currentBalance: number;
|
|
218
|
+
totalWithdrawn: number;
|
|
219
|
+
profitSplitPercent: number;
|
|
220
|
+
createdAt?: string | null;
|
|
221
|
+
/** The passed challenge the account was created from. */
|
|
222
|
+
challengeId?: string | null;
|
|
223
|
+
payoutCount?: number;
|
|
224
|
+
maxPayouts?: number | null;
|
|
225
|
+
/** When it closed or was revoked. Null while active. */
|
|
226
|
+
endedAt?: string | null;
|
|
227
|
+
/** Payout requests on the account, newest first. */
|
|
228
|
+
payouts?: HistoryPayout[];
|
|
229
|
+
}
|
|
91
230
|
/** A challenge product tier (as returned by the public /challenge-tiers endpoint) */
|
|
92
231
|
export interface ChallengeTier {
|
|
93
232
|
id: string;
|
|
@@ -123,21 +262,50 @@ export interface ChallengeTier {
|
|
|
123
262
|
/** Lucky bet max profit as % of target */
|
|
124
263
|
luckyBetMaxProfitPercent: number;
|
|
125
264
|
}
|
|
126
|
-
/** Full challenge tier with admin-level fields (from /admin/challenge-tiers) */
|
|
127
|
-
export interface ChallengeTierFull
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
265
|
+
/** Full challenge tier with admin-level fields (from /admin/challenge-tiers). The bet limits live on the referenced rulesets. */
|
|
266
|
+
export interface ChallengeTierFull {
|
|
267
|
+
id: string;
|
|
268
|
+
tenantId: string;
|
|
269
|
+
name: string;
|
|
270
|
+
/** Own stake the user pays to enter */
|
|
271
|
+
ownStake: number;
|
|
272
|
+
/** Conditional bonus granted by the operator */
|
|
273
|
+
bonusAmount: number;
|
|
274
|
+
targetBalance: number;
|
|
275
|
+
durationDays: number;
|
|
133
276
|
challengeRulesetId: string;
|
|
134
277
|
fundedRulesetId: string;
|
|
278
|
+
fundedAccountBalance: number;
|
|
279
|
+
/** Profit split in user's favor (e.g. 80 = 80%) */
|
|
280
|
+
profitSplitPercent: number;
|
|
281
|
+
/** Max payout as % of funded balance per cycle. null = no cap */
|
|
282
|
+
payoutCapPercent: number | null;
|
|
283
|
+
/** @deprecated Decides nothing: every payout that includes the cycle share returns the balance to the funded amount. */
|
|
135
284
|
resetBalanceOnPayout: boolean;
|
|
136
285
|
fundedMinActiveDays: number;
|
|
137
286
|
fundedActiveDayPercent: number;
|
|
287
|
+
/** Whether the user may take back the own stake during the funded phase. */
|
|
288
|
+
fundedStakeRefundable?: boolean;
|
|
289
|
+
/** Lifetime payout cap on the funded account. Null = none. */
|
|
290
|
+
fundedTotalPayoutCap?: number | null;
|
|
291
|
+
/** Accepted bets required per payout cycle. */
|
|
292
|
+
fundedMinBets?: number;
|
|
293
|
+
/** Most payouts the funded account allows. Null = no limit. */
|
|
294
|
+
fundedMaxPayouts?: number | null;
|
|
295
|
+
/** Smallest payout that may be requested. Null = none. */
|
|
296
|
+
fundedMinPayout?: number | null;
|
|
297
|
+
/** Days between payouts. Null = no interval. */
|
|
298
|
+
fundedPayoutIntervalDays?: number | null;
|
|
299
|
+
/** Balance at which a payout becomes mandatory. Null = never. */
|
|
300
|
+
fundedMandatoryPayoutThreshold?: number | null;
|
|
301
|
+
/** ISO 4217 currency code */
|
|
302
|
+
currency: string;
|
|
303
|
+
enabled: boolean;
|
|
138
304
|
createdAt: string;
|
|
139
305
|
updatedAt: string;
|
|
140
306
|
}
|
|
307
|
+
/** Body for creating a challenge tier: the fields the API requires, plus any optional ones. */
|
|
308
|
+
export type ChallengeTierCreateRequest = Pick<ChallengeTierFull, 'name' | 'ownStake' | 'bonusAmount' | 'targetBalance' | 'durationDays' | 'challengeRulesetId' | 'fundedRulesetId' | 'fundedAccountBalance' | 'profitSplitPercent' | 'payoutCapPercent' | 'resetBalanceOnPayout' | 'fundedMinActiveDays' | 'fundedActiveDayPercent'> & Partial<Omit<ChallengeTierFull, 'id' | 'tenantId' | 'createdAt' | 'updatedAt'>>;
|
|
141
309
|
/** Rules engine validation result */
|
|
142
310
|
export interface ValidationResult {
|
|
143
311
|
/** accepted = passes all rules, rejected = violates rules, flagged = accepted but noted */
|
|
@@ -160,8 +328,17 @@ export interface Ruleset {
|
|
|
160
328
|
dailyDrawdownPercent: number;
|
|
161
329
|
totalDrawdownPercent: number;
|
|
162
330
|
cooldownDurationHours: number | null;
|
|
163
|
-
balanceCalculationBasis
|
|
164
|
-
|
|
331
|
+
balanceCalculationBasis?: 'original' | 'current';
|
|
332
|
+
/** Max selections in an accumulator bet. 0 = no limit. */
|
|
333
|
+
maxAccumulatorSelections?: number;
|
|
334
|
+
/** Absolute cap on potential win per ticket. Null = no cap. */
|
|
335
|
+
maxWinPerTicket?: number | null;
|
|
336
|
+
/** Basis for the daily drawdown calculation. */
|
|
337
|
+
sessionStopBasis?: 'original' | 'current';
|
|
338
|
+
enabled?: boolean;
|
|
339
|
+
tenantId?: string;
|
|
340
|
+
createdAt?: string;
|
|
341
|
+
updatedAt?: string;
|
|
165
342
|
}
|
|
166
343
|
/** Live challenge progress for sportsbook UI */
|
|
167
344
|
export interface ChallengeProgress {
|
|
@@ -208,7 +385,18 @@ export interface FundedAccountProgress {
|
|
|
208
385
|
fundedAccountId: string;
|
|
209
386
|
currentBalance: number;
|
|
210
387
|
fundedAmount: number;
|
|
211
|
-
|
|
388
|
+
/** @deprecated Never returned by the API; always undefined. */
|
|
389
|
+
purchasePrice?: number;
|
|
390
|
+
/** Own stake the user paid to enter. */
|
|
391
|
+
ownStake?: number;
|
|
392
|
+
/** Operator bonus: never withdrawable. */
|
|
393
|
+
nonWithdrawableBonus?: number;
|
|
394
|
+
/** Own stake the user can still take back with `refundFundedStake` (0 when not allowed). */
|
|
395
|
+
refundableOwnStake?: number;
|
|
396
|
+
/** Whether the tier allows an own-stake refund in the funded phase. */
|
|
397
|
+
stakeRefundable?: boolean;
|
|
398
|
+
/** Lifetime payout cap, null for none. */
|
|
399
|
+
totalPayoutCap?: number | null;
|
|
212
400
|
withdrawableProfit: number;
|
|
213
401
|
earnedProfit: number;
|
|
214
402
|
rawProfit: number;
|
|
@@ -218,8 +406,23 @@ export interface FundedAccountProgress {
|
|
|
218
406
|
totalWithdrawn: number;
|
|
219
407
|
activeDays: number;
|
|
220
408
|
minActiveDays: number;
|
|
221
|
-
status: 'active';
|
|
409
|
+
status: 'active' | 'closed' | 'revoked';
|
|
222
410
|
reserved: number;
|
|
411
|
+
/** Stake on bets not yet settled. */
|
|
412
|
+
openStake?: number;
|
|
413
|
+
payoutCount?: number;
|
|
414
|
+
maxPayouts?: number | null;
|
|
415
|
+
unpaidProfit?: number;
|
|
416
|
+
/** Accepted bets in the current payout cycle. */
|
|
417
|
+
totalBetsAccepted?: number;
|
|
418
|
+
/** Stake a day needs for it to count as an active day. */
|
|
419
|
+
activeDayThreshold?: number;
|
|
420
|
+
/** Stake placed today towards `activeDayThreshold`. */
|
|
421
|
+
todayWagered?: number;
|
|
422
|
+
minBetsRequired?: number;
|
|
423
|
+
maxWinPerTicket?: number | null;
|
|
424
|
+
payout?: PayoutState | null;
|
|
425
|
+
lastPayoutRequest?: Pick<PayoutRequest, 'id' | 'amount' | 'status' | 'rejectionReason' | 'isFinal' | 'isMandatory' | 'createdAt' | 'decidedAt'> | null;
|
|
223
426
|
currency?: string;
|
|
224
427
|
selfExcluded?: boolean;
|
|
225
428
|
}
|
|
@@ -227,6 +430,11 @@ export interface FundedAccountProgress {
|
|
|
227
430
|
export interface NoProgress {
|
|
228
431
|
type: 'none';
|
|
229
432
|
message: string;
|
|
433
|
+
/** How the last programme ended: a failed challenge, or a funded account that finished. */
|
|
434
|
+
lastOutcome?: (Record<string, unknown> & {
|
|
435
|
+
type: 'challenge_failed' | 'funded_closed';
|
|
436
|
+
endedAt: string;
|
|
437
|
+
}) | null;
|
|
230
438
|
selfExcluded?: boolean;
|
|
231
439
|
}
|
|
232
440
|
/** Discriminated union - check the `type` field */
|
|
@@ -241,12 +449,23 @@ export interface WithdrawableInfo {
|
|
|
241
449
|
activeDaysCount: number;
|
|
242
450
|
minActiveDays: number;
|
|
243
451
|
activeDaysMet: boolean;
|
|
452
|
+
payout: PayoutState;
|
|
244
453
|
}
|
|
245
|
-
/**
|
|
454
|
+
/** Payout request result. `executed` carries the profit split breakdown. */
|
|
246
455
|
export interface WithdrawalResult {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
456
|
+
status: 'pending' | 'executed';
|
|
457
|
+
payoutRequestId: string;
|
|
458
|
+
amount: number;
|
|
459
|
+
isFinal: boolean;
|
|
460
|
+
newBalance?: number;
|
|
461
|
+
userPayout?: number;
|
|
462
|
+
ownStakeReturned?: number;
|
|
463
|
+
totalPayout?: number;
|
|
464
|
+
operatorShare?: number;
|
|
465
|
+
resetApplied?: boolean;
|
|
466
|
+
unpaidProfit?: number;
|
|
467
|
+
forfeitedProfit?: number;
|
|
468
|
+
accountClosed?: boolean;
|
|
250
469
|
}
|
|
251
470
|
/** Bet ingestion result (sync or async mode) */
|
|
252
471
|
export interface BetIngestResult {
|
|
@@ -255,17 +474,35 @@ export interface BetIngestResult {
|
|
|
255
474
|
validationResult?: ValidationResult;
|
|
256
475
|
message?: string;
|
|
257
476
|
}
|
|
477
|
+
/** One bet's outcome in a batch. */
|
|
478
|
+
export interface BatchBetItemResult {
|
|
479
|
+
/** Zero-based position of the bet in the submitted array. */
|
|
480
|
+
index: number;
|
|
481
|
+
/**
|
|
482
|
+
* The submitted bet's externalBetId, filled in by the SDK from `index`.
|
|
483
|
+
* @sdkComputed
|
|
484
|
+
*/
|
|
485
|
+
externalBetId?: string;
|
|
486
|
+
/** processed (sync mode), accepted (async mode, queued), or error. */
|
|
487
|
+
status: 'processed' | 'accepted' | 'error';
|
|
488
|
+
validationResult?: ValidationResult;
|
|
489
|
+
/** Why the bet failed, when status is 'error'. */
|
|
490
|
+
error?: string;
|
|
491
|
+
}
|
|
258
492
|
/** Batch bet ingestion result */
|
|
259
493
|
export interface BatchBetResult {
|
|
494
|
+
status: 'completed';
|
|
260
495
|
total: number;
|
|
496
|
+
/** Bets processed or accepted. */
|
|
497
|
+
succeeded: number;
|
|
498
|
+
/**
|
|
499
|
+
* @deprecated Use `succeeded`. Kept as an alias, filled in by the SDK.
|
|
500
|
+
* @sdkComputed
|
|
501
|
+
*/
|
|
261
502
|
processed: number;
|
|
262
503
|
failed: number;
|
|
263
|
-
results
|
|
264
|
-
|
|
265
|
-
status: 'processed' | 'failed';
|
|
266
|
-
validationResult?: ValidationResult;
|
|
267
|
-
error?: string;
|
|
268
|
-
}>;
|
|
504
|
+
/** Per-bet results in submission order. */
|
|
505
|
+
results: BatchBetItemResult[];
|
|
269
506
|
}
|
|
270
507
|
/** Reconciliation data for cross-referencing with sportsbook records */
|
|
271
508
|
export interface ReconciliationData {
|
|
@@ -280,13 +517,46 @@ export interface SseToken {
|
|
|
280
517
|
ttl: number;
|
|
281
518
|
userId: string;
|
|
282
519
|
}
|
|
283
|
-
/**
|
|
520
|
+
/** The ruleset limits disclosed with a tier's terms. */
|
|
521
|
+
export interface TierTermsRules {
|
|
522
|
+
maxStakePercent: number;
|
|
523
|
+
minOdds: number;
|
|
524
|
+
maxOdds: number;
|
|
525
|
+
maxPayoutMultiplier: number;
|
|
526
|
+
maxWinPerTicket: number | null;
|
|
527
|
+
minBetsRequired: number;
|
|
528
|
+
minActiveDays: number;
|
|
529
|
+
dailyDrawdownPercent: number;
|
|
530
|
+
totalDrawdownPercent: number;
|
|
531
|
+
cooldownDurationHours: number | null;
|
|
532
|
+
luckyBetMaxProfitPercent: number;
|
|
533
|
+
luckyBetMaxOdds: number;
|
|
534
|
+
balanceCalculationBasis: string;
|
|
535
|
+
}
|
|
536
|
+
/** Language of the human-readable terms and disclosures. */
|
|
537
|
+
export type TermsLanguage = 'en' | 'hr' | 'de';
|
|
538
|
+
/** Challenge tier terms and disclosures (regulatory compliance), as GET /challenge-tiers/:id/terms returns them. */
|
|
284
539
|
export interface TierTerms {
|
|
285
540
|
tierId: string;
|
|
286
541
|
tierName: string;
|
|
287
|
-
|
|
542
|
+
purchasePrice: number;
|
|
543
|
+
ownStake: number;
|
|
544
|
+
bonusAmount: number;
|
|
545
|
+
currency: string;
|
|
546
|
+
/** Balance the user plays with: own stake + bonus. */
|
|
547
|
+
challengeBalance: number;
|
|
548
|
+
targetBalance: number;
|
|
549
|
+
durationDays: number;
|
|
550
|
+
/** Base balance of the reward (funded) account on continuing. */
|
|
551
|
+
rewardAccountBalance: number;
|
|
552
|
+
profitSplitPercent: number;
|
|
553
|
+
payoutCapPercent: number | null;
|
|
554
|
+
/** @deprecated Decides nothing: every payout that includes the cycle share returns the balance to the funded amount. */
|
|
555
|
+
resetBalanceOnPayout?: boolean;
|
|
556
|
+
rules: TierTermsRules;
|
|
557
|
+
/** Sentences to show the user before purchase, in `lang`. */
|
|
288
558
|
disclosures: string[];
|
|
289
|
-
|
|
559
|
+
lang: TermsLanguage;
|
|
290
560
|
}
|
|
291
561
|
/** Webhook event payload delivered to your endpoint */
|
|
292
562
|
export interface WebhookPayload<T = Record<string, unknown>> {
|
|
@@ -296,9 +566,8 @@ export interface WebhookPayload<T = Record<string, unknown>> {
|
|
|
296
566
|
timestamp: string;
|
|
297
567
|
data: T;
|
|
298
568
|
}
|
|
299
|
-
/**
|
|
300
|
-
export interface
|
|
301
|
-
id: string;
|
|
569
|
+
/** Fields every achievement carries, earned or not. */
|
|
570
|
+
export interface AchievementBase {
|
|
302
571
|
code: string;
|
|
303
572
|
name: string;
|
|
304
573
|
description: string;
|
|
@@ -306,20 +575,33 @@ export interface Achievement {
|
|
|
306
575
|
category: string;
|
|
307
576
|
points: number;
|
|
308
577
|
rarity: 'common' | 'rare' | 'epic' | 'legendary';
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
578
|
+
}
|
|
579
|
+
/** An achievement the user has earned. */
|
|
580
|
+
export interface Achievement extends AchievementBase {
|
|
581
|
+
earnedAt: string;
|
|
582
|
+
metadata: Record<string, unknown> | null;
|
|
583
|
+
}
|
|
584
|
+
/** An achievement not yet earned, with progress towards it. */
|
|
585
|
+
export interface LockedAchievement extends AchievementBase {
|
|
586
|
+
sortOrder: number;
|
|
587
|
+
/** What earns it: `progress` counts towards `threshold`. */
|
|
588
|
+
criteria: {
|
|
589
|
+
type: string;
|
|
590
|
+
threshold: number;
|
|
591
|
+
} | null;
|
|
592
|
+
progress: number;
|
|
313
593
|
}
|
|
314
594
|
/** User achievements response */
|
|
315
595
|
export interface UserAchievements {
|
|
596
|
+
/** Earned achievements, most recent first. */
|
|
316
597
|
achievements: Achievement[];
|
|
598
|
+
/** Achievements not yet earned, in display order. */
|
|
599
|
+
locked: LockedAchievement[];
|
|
317
600
|
totalPoints: number;
|
|
318
601
|
level: number;
|
|
319
602
|
streak: {
|
|
320
603
|
current: number;
|
|
321
604
|
longest: number;
|
|
322
|
-
lastActiveDate: string | null;
|
|
323
605
|
};
|
|
324
606
|
}
|
|
325
607
|
/** Reward type */
|
|
@@ -330,11 +612,15 @@ export type RewardApplyMode = 'auto' | 'claim';
|
|
|
330
612
|
export interface Reward {
|
|
331
613
|
id: string;
|
|
332
614
|
rewardType: RewardType;
|
|
615
|
+
/** In EUR for money types, otherwise percent or days. */
|
|
333
616
|
rewardValue: number;
|
|
617
|
+
/** On claimable items the API omits this; the SDK fills `'claim'`. */
|
|
334
618
|
applyMode: RewardApplyMode;
|
|
619
|
+
/** ISO 8601, or null when it never expires. */
|
|
335
620
|
expiresAt: string | null;
|
|
336
621
|
achievementCode: string | null;
|
|
337
622
|
achievementName: string | null;
|
|
623
|
+
/** ISO 8601 */
|
|
338
624
|
createdAt: string;
|
|
339
625
|
}
|
|
340
626
|
/** User rewards response */
|
|
@@ -344,10 +630,9 @@ export interface UserRewards {
|
|
|
344
630
|
/** Rewards waiting for user to claim */
|
|
345
631
|
claimable: Reward[];
|
|
346
632
|
}
|
|
347
|
-
/** Reward claim result */
|
|
633
|
+
/** Reward claim result. Read the reward back with `users.getRewards()` if you need it. */
|
|
348
634
|
export interface RewardClaimResult {
|
|
349
635
|
claimed: boolean;
|
|
350
|
-
reward: Reward;
|
|
351
636
|
}
|
|
352
637
|
/** Leaderboard entry */
|
|
353
638
|
export interface LeaderboardEntry {
|
|
@@ -380,27 +665,41 @@ export interface SandboxResetResult {
|
|
|
380
665
|
export interface SandboxUserResetResult {
|
|
381
666
|
status: string;
|
|
382
667
|
userId: string;
|
|
383
|
-
|
|
668
|
+
/** Which kinds of data were cleared (challenges, fundedAccounts, betEvents, webhookDeliveries). */
|
|
669
|
+
deleted: Record<string, boolean>;
|
|
384
670
|
}
|
|
385
671
|
/** Bet event as returned by admin endpoints */
|
|
386
672
|
export interface AdminBetEvent {
|
|
387
673
|
id: string;
|
|
674
|
+
tenantId?: string;
|
|
388
675
|
userId: string;
|
|
389
676
|
externalBetId: string;
|
|
677
|
+
challengeId?: string | null;
|
|
678
|
+
fundedAccountId?: string | null;
|
|
390
679
|
stakeAmount: number;
|
|
391
680
|
odds: number;
|
|
681
|
+
betTypeIdentifier?: string | null;
|
|
392
682
|
status: BetStatus;
|
|
683
|
+
isCashOut?: boolean;
|
|
393
684
|
validationResult: ValidationStatus | null;
|
|
394
|
-
|
|
685
|
+
/** Rule violation codes. Empty when accepted. */
|
|
686
|
+
rejectionReasons: RejectionCode[];
|
|
687
|
+
/**
|
|
688
|
+
* @deprecated The API calls this `rejectionReasons`; the SDK fills this alias from it.
|
|
689
|
+
* @sdkComputed
|
|
690
|
+
*/
|
|
691
|
+
reasonCodes?: RejectionCode[];
|
|
395
692
|
settlementAmount: number | null;
|
|
693
|
+
currency?: string;
|
|
396
694
|
eventTimestamp: string;
|
|
695
|
+
processedAt?: string | null;
|
|
397
696
|
createdAt: string;
|
|
398
697
|
}
|
|
399
698
|
/** Settle a bet event */
|
|
400
699
|
export interface BetSettleRequest {
|
|
401
700
|
outcome: 'won' | 'lost';
|
|
402
701
|
}
|
|
403
|
-
/** Bulk settle request */
|
|
702
|
+
/** Bulk settle request (max 50 settlements per call) */
|
|
404
703
|
export interface BulkSettleRequest {
|
|
405
704
|
settlements: Array<{
|
|
406
705
|
betEventId: string;
|
|
@@ -411,6 +710,10 @@ export interface BulkSettleRequest {
|
|
|
411
710
|
export interface BulkSettleResult {
|
|
412
711
|
results: Array<{
|
|
413
712
|
betEventId: string;
|
|
713
|
+
status: 'settled' | 'error';
|
|
714
|
+
/** Why it was not settled, e.g. `not_found`, `already_settled`. */
|
|
715
|
+
error?: string;
|
|
716
|
+
/** @deprecated Use `status === 'settled'`. Filled in by the SDK. */
|
|
414
717
|
success: boolean;
|
|
415
718
|
}>;
|
|
416
719
|
settled: number;
|
|
@@ -422,120 +725,294 @@ export interface WebhookDelivery {
|
|
|
422
725
|
eventId: string;
|
|
423
726
|
eventType: WebhookEventType;
|
|
424
727
|
userId: string;
|
|
728
|
+
/** The exact body that was (or will be) POSTed. */
|
|
729
|
+
payload: WebhookPayload;
|
|
730
|
+
webhookUrl: string;
|
|
425
731
|
status: WebhookDeliveryStatus;
|
|
426
732
|
responseStatus: number | null;
|
|
427
733
|
attempts: number;
|
|
428
734
|
lastAttemptAt: string | null;
|
|
429
735
|
createdAt: string;
|
|
430
736
|
}
|
|
431
|
-
/**
|
|
737
|
+
/** A webhook delivery that exhausted its retries. */
|
|
738
|
+
export interface WebhookDeadLetter {
|
|
739
|
+
id: string;
|
|
740
|
+
tenantId: string;
|
|
741
|
+
deliveryId: string;
|
|
742
|
+
eventId: string;
|
|
743
|
+
eventType: WebhookEventType;
|
|
744
|
+
userId: string;
|
|
745
|
+
payload: WebhookPayload;
|
|
746
|
+
webhookUrl: string;
|
|
747
|
+
finalAttempts: number;
|
|
748
|
+
lastError: string | null;
|
|
749
|
+
/** When it was replayed. Null until then; a dead letter replays once. */
|
|
750
|
+
replayedAt: string | null;
|
|
751
|
+
replayDeliveryId: string | null;
|
|
752
|
+
createdAt: string;
|
|
753
|
+
}
|
|
754
|
+
/** Result of rotating the webhook signing secret. */
|
|
755
|
+
export interface WebhookSecretRotation {
|
|
756
|
+
/** The new signing secret. Shown once: store it now. */
|
|
757
|
+
newSecret: string;
|
|
758
|
+
/** Hours the old secret keeps being accepted. */
|
|
759
|
+
gracePeriodHours: number;
|
|
760
|
+
oldSecretExpiresAt: string;
|
|
761
|
+
/** @deprecated Use `newSecret`. Filled in by the SDK. */
|
|
762
|
+
webhookSecret: string;
|
|
763
|
+
}
|
|
764
|
+
/** Admin audit log entry (GET /admin/audit-log) */
|
|
432
765
|
export interface AuditEntry {
|
|
433
766
|
id: string;
|
|
767
|
+
tenantId: string;
|
|
434
768
|
action: string;
|
|
769
|
+
/** Admin email, or `api-key` for server-key calls. */
|
|
435
770
|
actor: string;
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
771
|
+
resourceType: string | null;
|
|
772
|
+
resourceId: string | null;
|
|
773
|
+
details: Record<string, unknown> | null;
|
|
774
|
+
ipAddress: string | null;
|
|
440
775
|
createdAt: string;
|
|
441
776
|
}
|
|
777
|
+
/** Which ledger GET /audit/log reads. */
|
|
778
|
+
export type AuditLogType = 'bets' | 'webhooks';
|
|
779
|
+
/** Page of GET /audit/log: bet events or webhook deliveries. */
|
|
780
|
+
export interface AuditLogPage {
|
|
781
|
+
/** `bet_events` or `webhook_deliveries`. */
|
|
782
|
+
type: string;
|
|
783
|
+
total: number;
|
|
784
|
+
limit: number;
|
|
785
|
+
offset: number;
|
|
786
|
+
entries: Array<Record<string, unknown>>;
|
|
787
|
+
}
|
|
442
788
|
/** Tenant settings */
|
|
443
789
|
export interface TenantSettings {
|
|
790
|
+
tenantId?: string;
|
|
791
|
+
name?: string;
|
|
792
|
+
environment?: string;
|
|
444
793
|
integrationMode: IntegrationMode;
|
|
445
794
|
webhookUrl: string | null;
|
|
446
795
|
/** Single URL FAST calls before any money/irreversible action (type in payload). */
|
|
447
796
|
approvalUrl: string | null;
|
|
448
797
|
operatorChallengeLimit: number | null;
|
|
798
|
+
monthlyChallengeLimit?: number | null;
|
|
799
|
+
effectiveChallengeLimit?: number | null;
|
|
800
|
+
revenueSharePercent?: number;
|
|
801
|
+
exposureAlertThreshold?: number | null;
|
|
802
|
+
exportEnabled?: boolean;
|
|
803
|
+
exportEmail?: string | null;
|
|
804
|
+
exportWebhookUrl?: string | null;
|
|
805
|
+
defaultCurrency?: string;
|
|
806
|
+
supportedCurrencies?: string[];
|
|
807
|
+
widgetLayout?: {
|
|
808
|
+
fundedOnly: boolean;
|
|
809
|
+
history: boolean;
|
|
810
|
+
};
|
|
811
|
+
createdAt?: string;
|
|
449
812
|
}
|
|
450
|
-
/** Admin overview stats */
|
|
813
|
+
/** Admin overview stats (GET /admin/overview) */
|
|
451
814
|
export interface AdminOverview {
|
|
815
|
+
period: {
|
|
816
|
+
month: number;
|
|
817
|
+
year: number;
|
|
818
|
+
};
|
|
819
|
+
/** Count per challenge status. */
|
|
452
820
|
challenges: Record<string, number>;
|
|
821
|
+
/** Count per funded account status. */
|
|
453
822
|
fundedAccounts: Record<string, number>;
|
|
454
|
-
|
|
455
|
-
|
|
823
|
+
revenue: {
|
|
824
|
+
allTime: Record<string, number>;
|
|
825
|
+
/** Includes `uniqueUsers` for the month. */
|
|
826
|
+
month: Record<string, number>;
|
|
827
|
+
revenueShare: Record<string, number>;
|
|
828
|
+
};
|
|
829
|
+
exposure: Record<string, unknown>;
|
|
830
|
+
usage: Record<string, number>;
|
|
456
831
|
}
|
|
457
|
-
/** Bonus
|
|
832
|
+
/** Bonus type */
|
|
833
|
+
export type BonusType = 'deposit_match' | 'free_bet' | 'no_deposit' | 'cashback' | 'reload';
|
|
834
|
+
/** Bonus offer (admin). Money fields are integer cents. */
|
|
458
835
|
export interface BonusOffer {
|
|
459
836
|
id: string;
|
|
837
|
+
tenantId?: string;
|
|
460
838
|
name: string;
|
|
461
|
-
|
|
839
|
+
description: string | null;
|
|
840
|
+
bonusType: BonusType;
|
|
462
841
|
matchPercent: number | null;
|
|
842
|
+
/** Integer cents. */
|
|
463
843
|
maxBonusAmount: number;
|
|
464
844
|
wageringMultiplier: number;
|
|
465
|
-
durationDays: number;
|
|
466
845
|
minOdds: number | null;
|
|
846
|
+
/** Integer cents. */
|
|
847
|
+
maxBetFromBonus: number | null;
|
|
848
|
+
excludedMarkets: string[] | null;
|
|
849
|
+
durationDays: number;
|
|
850
|
+
/** Integer cents. */
|
|
851
|
+
minQualifyingDeposit: number | null;
|
|
852
|
+
maxActivations: number | null;
|
|
467
853
|
maxPerUser: number | null;
|
|
854
|
+
stackable: boolean;
|
|
468
855
|
forfeitOnWithdrawal: boolean;
|
|
469
856
|
enabled: boolean;
|
|
857
|
+
startsAt: string | null;
|
|
858
|
+
endsAt: string | null;
|
|
859
|
+
sortOrder: number;
|
|
470
860
|
createdAt: string;
|
|
861
|
+
updatedAt: string;
|
|
471
862
|
}
|
|
472
|
-
/** Bonus stats */
|
|
863
|
+
/** Bonus stats (GET /admin/bonuses/stats) */
|
|
473
864
|
export interface BonusStats {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
865
|
+
activeCount: number;
|
|
866
|
+
/** Percent of bonuses completed over the last 30 days. */
|
|
867
|
+
completionRate30d: number;
|
|
868
|
+
/** Bonus balance outstanding, integer cents. */
|
|
869
|
+
totalOutstanding: number;
|
|
870
|
+
avgProgress: number;
|
|
478
871
|
}
|
|
479
872
|
/** Mission definition (admin) */
|
|
480
873
|
export interface MissionDef {
|
|
481
874
|
id: string;
|
|
875
|
+
tenantId?: string;
|
|
482
876
|
name: string;
|
|
483
877
|
description: string | null;
|
|
878
|
+
icon: string | null;
|
|
484
879
|
criteriaType: string;
|
|
485
880
|
criteriaThreshold: number;
|
|
881
|
+
criteriaMeta: Record<string, unknown> | null;
|
|
486
882
|
rewardType: string | null;
|
|
883
|
+
/** In cents for money types (bonus credit, free bet, fixed discount...), otherwise percent, days or points. Unlike reward rules and grants, which take EUR. */
|
|
487
884
|
rewardValue: number;
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
885
|
+
rewardApplyMode: string;
|
|
886
|
+
startsAt: string;
|
|
887
|
+
endsAt: string;
|
|
888
|
+
enrollmentMode: 'auto' | 'opt_in' | 'targeted';
|
|
889
|
+
repeatable: boolean;
|
|
890
|
+
maxCompletionsPerUser: number;
|
|
491
891
|
enabled: boolean;
|
|
892
|
+
sortOrder: number;
|
|
492
893
|
createdAt: string;
|
|
894
|
+
updatedAt: string;
|
|
895
|
+
}
|
|
896
|
+
/** Fields the API assigns itself and drops from a request body. */
|
|
897
|
+
type ServerManaged = 'id' | 'tenantId' | 'createdAt' | 'updatedAt';
|
|
898
|
+
/** Body for creating a mission: the fields the API requires, plus any optional ones. A new mission starts enabled. */
|
|
899
|
+
export type MissionCreateRequest = Pick<MissionDef, 'name' | 'criteriaType' | 'criteriaThreshold' | 'startsAt' | 'endsAt'> & Partial<Omit<MissionDef, ServerManaged | 'enabled'>>;
|
|
900
|
+
/** Body for updating a mission: any subset of its editable fields. */
|
|
901
|
+
export type MissionUpdateRequest = Partial<Omit<MissionDef, ServerManaged>>;
|
|
902
|
+
type RulesetRequired = 'name' | 'maxStakePercent' | 'minOdds' | 'maxOdds' | 'maxPayoutMultiplier' | 'dailyDrawdownPercent' | 'totalDrawdownPercent' | 'minActiveDays' | 'minBetsRequired' | 'luckyBetMaxOdds' | 'luckyBetMaxProfitPercent';
|
|
903
|
+
/** Body for creating a ruleset: the limits the API requires, plus any optional ones. */
|
|
904
|
+
export type RulesetCreateRequest = Pick<Ruleset, RulesetRequired> & Partial<Omit<Ruleset, RulesetRequired | ServerManaged>>;
|
|
905
|
+
/** Body for updating a ruleset: any subset of its editable fields. */
|
|
906
|
+
export type RulesetUpdateRequest = Partial<Omit<Ruleset, ServerManaged>>;
|
|
907
|
+
/** Body for creating a bonus offer. A new offer starts enabled. */
|
|
908
|
+
export type BonusOfferCreateRequest = Pick<BonusOffer, 'name' | 'bonusType' | 'maxBonusAmount'> & Partial<Omit<BonusOffer, 'name' | 'bonusType' | 'maxBonusAmount' | 'enabled' | ServerManaged>>;
|
|
909
|
+
/** Body for updating a bonus offer. The bonus type is fixed once created. */
|
|
910
|
+
export type BonusOfferUpdateRequest = Partial<Omit<BonusOffer, 'bonusType' | ServerManaged>>;
|
|
911
|
+
/** Body for updating the loyalty programme configuration. */
|
|
912
|
+
export type LoyaltyConfigUpdateRequest = Partial<Omit<LoyaltyConfig, ServerManaged>>;
|
|
913
|
+
/** Tournament lifecycle state */
|
|
914
|
+
export type TournamentStatus = 'upcoming' | 'active' | 'settling' | 'completed' | 'cancelled';
|
|
915
|
+
/** A prize band: ranks rankFrom..rankTo each receive the reward. */
|
|
916
|
+
export interface TournamentPrize {
|
|
917
|
+
rankFrom: number;
|
|
918
|
+
rankTo: number;
|
|
919
|
+
rewardType: string;
|
|
920
|
+
/** In cents for money types, otherwise percent, days or points. */
|
|
921
|
+
rewardValue: number;
|
|
493
922
|
}
|
|
494
923
|
/** Tournament definition (admin) */
|
|
495
924
|
export interface TournamentDef {
|
|
496
925
|
id: string;
|
|
926
|
+
tenantId?: string;
|
|
497
927
|
name: string;
|
|
498
928
|
description: string | null;
|
|
499
|
-
|
|
500
|
-
entryMode: 'free' | 'paid';
|
|
501
|
-
entryFee: number;
|
|
502
|
-
prizePool: number;
|
|
503
|
-
maxEntrants: number | null;
|
|
504
|
-
scoringMetric: string;
|
|
929
|
+
scoringMetric: 'net_profit' | 'total_wagered' | 'win_count' | 'bet_count' | 'highest_odds_won' | 'longest_win_streak';
|
|
505
930
|
startsAt: string;
|
|
506
931
|
endsAt: string;
|
|
932
|
+
entryMode: 'auto' | 'opt_in' | 'invite';
|
|
933
|
+
minBetsToQualify: number;
|
|
934
|
+
maxParticipants: number | null;
|
|
935
|
+
prizes: TournamentPrize[];
|
|
936
|
+
tiebreaker: 'earliest_entry' | 'most_bets' | 'highest_single_win' | null;
|
|
937
|
+
status: TournamentStatus;
|
|
938
|
+
totalEntries: number;
|
|
939
|
+
settledAt: string | null;
|
|
507
940
|
createdAt: string;
|
|
941
|
+
updatedAt?: string;
|
|
508
942
|
}
|
|
943
|
+
/** Body for creating a tournament: the fields the API requires, plus any optional ones. */
|
|
944
|
+
export type TournamentCreateRequest = Pick<TournamentDef, 'name' | 'scoringMetric' | 'startsAt' | 'endsAt' | 'prizes'> & Partial<Pick<TournamentDef, 'description' | 'entryMode' | 'minBetsToQualify' | 'maxParticipants' | 'tiebreaker'>>;
|
|
509
945
|
/** Tournament leaderboard entry */
|
|
510
946
|
export interface TournamentLeaderboardEntry {
|
|
511
947
|
rank: number;
|
|
512
948
|
userId: string;
|
|
949
|
+
/** Masked user id for display. */
|
|
513
950
|
displayName: string;
|
|
514
951
|
score: number;
|
|
515
|
-
|
|
952
|
+
qualifyingBets: number;
|
|
953
|
+
}
|
|
954
|
+
/** A tournament entry row as the admin entries list returns it. */
|
|
955
|
+
export interface TournamentEntry {
|
|
956
|
+
id: string;
|
|
957
|
+
tenantId: string;
|
|
958
|
+
tournamentId: string;
|
|
959
|
+
userId: string;
|
|
960
|
+
score: number | null;
|
|
961
|
+
qualifyingBets: number | null;
|
|
962
|
+
rank: number | null;
|
|
963
|
+
prizeType: string | null;
|
|
964
|
+
/** In cents for money types. */
|
|
965
|
+
prizeValue: number | null;
|
|
966
|
+
prizeGranted: boolean | null;
|
|
967
|
+
enteredAt: string | null;
|
|
968
|
+
lastScoreUpdate: string | null;
|
|
516
969
|
}
|
|
517
|
-
/** Loyalty config */
|
|
970
|
+
/** Loyalty config (GET/PUT /admin/loyalty/config) */
|
|
518
971
|
export interface LoyaltyConfig {
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
972
|
+
id?: string;
|
|
973
|
+
tenantId?: string;
|
|
974
|
+
/** Activity-to-points rules, e.g. `{ activity: 'bet_placed', pointsPerEurWagered: 1, maxPerDay: 500 }`. */
|
|
975
|
+
pointRules: Array<Record<string, unknown>>;
|
|
976
|
+
decayMode: string;
|
|
523
977
|
decayPercent: number | null;
|
|
978
|
+
cashbackEnabled: boolean;
|
|
979
|
+
cashbackSettleMode: string;
|
|
980
|
+
demotionEnabled: boolean;
|
|
981
|
+
demotionGraceDays: number;
|
|
982
|
+
enabled: boolean;
|
|
983
|
+
createdAt?: string;
|
|
984
|
+
updatedAt?: string;
|
|
524
985
|
}
|
|
525
986
|
/** Loyalty tier */
|
|
526
987
|
export interface LoyaltyTier {
|
|
527
988
|
id: string;
|
|
989
|
+
tenantId?: string;
|
|
528
990
|
name: string;
|
|
991
|
+
/** Rank order; higher is more prestigious. Required on create. */
|
|
992
|
+
level: number;
|
|
529
993
|
minPoints: number;
|
|
530
|
-
|
|
531
|
-
|
|
994
|
+
cashbackPercent: number;
|
|
995
|
+
benefits: unknown[];
|
|
996
|
+
icon: string;
|
|
997
|
+
color: string;
|
|
998
|
+
createdAt?: string;
|
|
532
999
|
}
|
|
1000
|
+
/** Body for creating a loyalty tier. */
|
|
1001
|
+
export type LoyaltyTierCreateRequest = Pick<LoyaltyTier, 'name' | 'level' | 'minPoints'> & Partial<Pick<LoyaltyTier, 'cashbackPercent' | 'benefits' | 'icon' | 'color'>>;
|
|
1002
|
+
/** Body for updating a loyalty tier: any subset of its editable fields. */
|
|
1003
|
+
export type LoyaltyTierUpdateRequest = Partial<Pick<LoyaltyTier, 'name' | 'level' | 'minPoints' | 'cashbackPercent' | 'benefits' | 'icon' | 'color'>>;
|
|
533
1004
|
/** Loyalty stats */
|
|
534
1005
|
export interface LoyaltyStats {
|
|
535
|
-
|
|
536
|
-
|
|
1006
|
+
totalUsers: number;
|
|
1007
|
+
avgPoints: number;
|
|
537
1008
|
totalCashbackPaid: number;
|
|
538
|
-
|
|
1009
|
+
/** Users active in the last 7 days. */
|
|
1010
|
+
active7d: number;
|
|
1011
|
+
tierDistribution: Array<{
|
|
1012
|
+
name: string;
|
|
1013
|
+
level: number;
|
|
1014
|
+
userCount: number;
|
|
1015
|
+
}>;
|
|
539
1016
|
}
|
|
540
1017
|
/** Webhook echo entry */
|
|
541
1018
|
export interface WebhookEchoEntry {
|
|
@@ -565,28 +1042,131 @@ export interface ReconciliationFlag {
|
|
|
565
1042
|
flaggedBy: string;
|
|
566
1043
|
createdAt: string;
|
|
567
1044
|
}
|
|
1045
|
+
/** Reward types an operator can grant or attach to a reward rule. */
|
|
1046
|
+
export type GrantableRewardType = 'balance_bonus' | 'balance_boost_percent' | 'purchase_discount_percent' | 'purchase_discount_fixed' | 'profit_split_boost' | 'extended_duration' | 'payout_cap_boost_percent';
|
|
568
1047
|
/** Reward rule definition (auto-grants rewards on criteria match) */
|
|
569
1048
|
export interface RewardRule {
|
|
570
1049
|
id: string;
|
|
1050
|
+
tenantId?: string;
|
|
571
1051
|
name: string;
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
1052
|
+
description: string | null;
|
|
1053
|
+
/** What triggers the grant: `type` reaching `threshold` (e.g. `{ type: 'active_days', threshold: 30 }`). */
|
|
1054
|
+
criteria: {
|
|
1055
|
+
type: string;
|
|
1056
|
+
threshold: number;
|
|
1057
|
+
};
|
|
1058
|
+
rewardType: GrantableRewardType;
|
|
1059
|
+
/** In EUR for money types, otherwise percent or days. Unlike missions and tournament prizes, which take cents. */
|
|
575
1060
|
rewardValue: number;
|
|
576
1061
|
applyMode: RewardApplyMode;
|
|
577
|
-
maxGrantsPerUser: number
|
|
1062
|
+
maxGrantsPerUser: number;
|
|
578
1063
|
expiresInDays: number | null;
|
|
579
1064
|
enabled: boolean;
|
|
580
1065
|
sortOrder: number;
|
|
581
1066
|
createdAt: string;
|
|
582
1067
|
}
|
|
1068
|
+
/** Body for creating an achievement definition. */
|
|
1069
|
+
export interface AchievementCreateRequest {
|
|
1070
|
+
/** Unique code within the tenant. */
|
|
1071
|
+
code: string;
|
|
1072
|
+
name: string;
|
|
1073
|
+
description?: string;
|
|
1074
|
+
icon?: string;
|
|
1075
|
+
category?: AchievementCategory;
|
|
1076
|
+
points?: number;
|
|
1077
|
+
/** Unlock criteria, evaluated by the achievement engine. */
|
|
1078
|
+
criteria?: Record<string, unknown>;
|
|
1079
|
+
/** Reward granted on unlock, or null for none. Money values in EUR. */
|
|
1080
|
+
reward?: {
|
|
1081
|
+
type: GrantableRewardType;
|
|
1082
|
+
value: number;
|
|
1083
|
+
applyMode?: RewardApplyMode;
|
|
1084
|
+
expiresInDays?: number | null;
|
|
1085
|
+
} | null;
|
|
1086
|
+
}
|
|
1087
|
+
export type AchievementCategory = 'general' | 'streak' | 'volume' | 'profit' | 'milestone';
|
|
1088
|
+
/** Body for updating an achievement definition. Its code and reward are fixed once created. */
|
|
1089
|
+
export type AchievementUpdateRequest = Partial<Pick<AchievementCreateRequest, 'name' | 'description' | 'icon' | 'category' | 'points' | 'criteria'>> & {
|
|
1090
|
+
enabled?: boolean;
|
|
1091
|
+
};
|
|
1092
|
+
/** Body for updating the widget theme. */
|
|
1093
|
+
export interface ThemeUpdateRequest {
|
|
1094
|
+
primaryColor?: string;
|
|
1095
|
+
secondaryColor?: string;
|
|
1096
|
+
fontFamily?: string;
|
|
1097
|
+
/** Absolute URL of the logo image. */
|
|
1098
|
+
logoUrl?: string;
|
|
1099
|
+
/** Text overrides keyed by copy id. */
|
|
1100
|
+
customCopy?: Record<string, unknown>;
|
|
1101
|
+
}
|
|
1102
|
+
/** Events an operator can switch notifications on or off for. */
|
|
1103
|
+
export type NotificationPreferenceEvent = 'bet.validation_result' | 'challenge.activated' | 'challenge.completed' | 'challenge.failed' | 'cooldown.triggered' | 'cooldown.lifted' | 'funded_account.activated' | 'funded_account.payout' | 'funded_account.payout_requested' | 'funded_account.payout_rejected' | 'funded_account.revoked' | 'user.self_excluded' | 'user.self_exclusion_lifted';
|
|
1104
|
+
/** Body for updating notification preferences: the events to change, true to notify. */
|
|
1105
|
+
export type NotificationPreferencesUpdate = Partial<Record<NotificationPreferenceEvent, boolean>>;
|
|
1106
|
+
/** Body for excluding a user. Without expiresAt or durationDays the exclusion is permanent. */
|
|
1107
|
+
export interface SelfExclusionRequest {
|
|
1108
|
+
userId: string;
|
|
1109
|
+
reason?: string;
|
|
1110
|
+
/** ISO 8601 end of the exclusion, or null for permanent. Wins over durationDays. */
|
|
1111
|
+
expiresAt?: string | null;
|
|
1112
|
+
/** Exclusion length in days from now; the SDK turns it into expiresAt. */
|
|
1113
|
+
durationDays?: number;
|
|
1114
|
+
/** E.g. a national registry reference. */
|
|
1115
|
+
metadata?: Record<string, unknown>;
|
|
1116
|
+
}
|
|
1117
|
+
/** Body for creating or updating a reward rule. */
|
|
1118
|
+
export interface RewardRuleInput {
|
|
1119
|
+
name?: string;
|
|
1120
|
+
description?: string;
|
|
1121
|
+
criteria?: {
|
|
1122
|
+
type: string;
|
|
1123
|
+
threshold: number;
|
|
1124
|
+
};
|
|
1125
|
+
rewardType?: GrantableRewardType;
|
|
1126
|
+
/** In EUR for money types, otherwise percent or days. */
|
|
1127
|
+
rewardValue?: number;
|
|
1128
|
+
applyMode?: RewardApplyMode;
|
|
1129
|
+
maxGrantsPerUser?: number;
|
|
1130
|
+
expiresInDays?: number | null;
|
|
1131
|
+
sortOrder?: number;
|
|
1132
|
+
/** Update only. */
|
|
1133
|
+
enabled?: boolean;
|
|
1134
|
+
/** @deprecated Use `criteria.type`. Mapped to `criteria` by the SDK. */
|
|
1135
|
+
triggerType?: string;
|
|
1136
|
+
/** @deprecated Use `criteria.threshold`. Mapped to `criteria` by the SDK. */
|
|
1137
|
+
triggerThreshold?: number;
|
|
1138
|
+
}
|
|
1139
|
+
/** A reward that has been applied, from the grant history. */
|
|
1140
|
+
export interface RewardApplication {
|
|
1141
|
+
id: string;
|
|
1142
|
+
tenantId: string;
|
|
1143
|
+
userId: string;
|
|
1144
|
+
rewardId: string;
|
|
1145
|
+
/** What it was applied to (challenge / funded account / purchase). */
|
|
1146
|
+
appliedTo: string;
|
|
1147
|
+
rewardType: string;
|
|
1148
|
+
rewardValue: number;
|
|
1149
|
+
effectDescription: string | null;
|
|
1150
|
+
appliedAt: string;
|
|
1151
|
+
originalType: string;
|
|
1152
|
+
achievementId: string | null;
|
|
1153
|
+
achievementCode: string | null;
|
|
1154
|
+
achievementName: string | null;
|
|
1155
|
+
}
|
|
583
1156
|
/** Self-exclusion record */
|
|
584
1157
|
export interface SelfExclusionRecord {
|
|
1158
|
+
id: string;
|
|
1159
|
+
tenantId: string;
|
|
585
1160
|
userId: string;
|
|
586
1161
|
reason: string;
|
|
1162
|
+
excludedBy: string | null;
|
|
1163
|
+
/** ISO 8601 */
|
|
587
1164
|
excludedAt: string;
|
|
1165
|
+
/** ISO 8601. Null = permanent. */
|
|
588
1166
|
expiresAt: string | null;
|
|
589
|
-
|
|
1167
|
+
metadata: Record<string, unknown>;
|
|
1168
|
+
/** ISO 8601 */
|
|
1169
|
+
createdAt: string;
|
|
590
1170
|
}
|
|
591
1171
|
/** Standard API error response */
|
|
592
1172
|
export interface FastError {
|
|
@@ -648,4 +1228,5 @@ export interface FastClientConfig {
|
|
|
648
1228
|
*/
|
|
649
1229
|
dangerouslyAllowBrowser?: boolean;
|
|
650
1230
|
}
|
|
1231
|
+
export {};
|
|
651
1232
|
//# sourceMappingURL=types.d.ts.map
|