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