@scorio/client-sdk 1.0.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/dist/index.d.ts +564 -0
- package/dist/index.js +623 -0
- package/dist/index.js.map +1 -0
- package/package.json +61 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
interface ListResponse<T> {
|
|
2
|
+
readonly data: readonly T[];
|
|
3
|
+
readonly meta: {
|
|
4
|
+
readonly count: number;
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
interface SingleResponse<T> {
|
|
8
|
+
readonly data: T;
|
|
9
|
+
}
|
|
10
|
+
interface Sport {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly name: string;
|
|
13
|
+
readonly alias: string;
|
|
14
|
+
readonly category: 'sport' | 'esport' | 'virtual' | 'racing' | 'fighting';
|
|
15
|
+
}
|
|
16
|
+
interface SportCount extends Sport {
|
|
17
|
+
readonly live_count: number;
|
|
18
|
+
readonly prematch_count: number;
|
|
19
|
+
}
|
|
20
|
+
interface Region {
|
|
21
|
+
readonly id: string;
|
|
22
|
+
readonly name: string;
|
|
23
|
+
readonly alias: string;
|
|
24
|
+
readonly sport_id: string;
|
|
25
|
+
}
|
|
26
|
+
interface Competition {
|
|
27
|
+
readonly id: string;
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly region_id: string;
|
|
30
|
+
readonly sport_id: string;
|
|
31
|
+
}
|
|
32
|
+
interface GameInfo {
|
|
33
|
+
readonly game_state: string;
|
|
34
|
+
readonly score: readonly [number, number];
|
|
35
|
+
readonly game_time?: number;
|
|
36
|
+
readonly set_count?: number;
|
|
37
|
+
readonly add_info?: string;
|
|
38
|
+
readonly stoppage_time?: {
|
|
39
|
+
readonly first_half?: string;
|
|
40
|
+
readonly second_half?: string;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
interface GameStats {
|
|
44
|
+
readonly [key: string]: readonly number[] | readonly (readonly number[])[];
|
|
45
|
+
}
|
|
46
|
+
interface Outcome {
|
|
47
|
+
readonly id: string;
|
|
48
|
+
readonly name: string;
|
|
49
|
+
readonly price: number;
|
|
50
|
+
readonly is_suspended: boolean;
|
|
51
|
+
}
|
|
52
|
+
interface Market {
|
|
53
|
+
readonly id: string;
|
|
54
|
+
readonly name: string;
|
|
55
|
+
readonly type: string;
|
|
56
|
+
readonly line: number | null;
|
|
57
|
+
readonly outcomes: readonly Outcome[];
|
|
58
|
+
}
|
|
59
|
+
interface Game {
|
|
60
|
+
readonly id: string;
|
|
61
|
+
readonly home_team: string;
|
|
62
|
+
readonly away_team: string;
|
|
63
|
+
readonly status: 'prematch' | 'live' | 'ended';
|
|
64
|
+
readonly start_time: number;
|
|
65
|
+
readonly is_live: boolean;
|
|
66
|
+
readonly markets_count: number;
|
|
67
|
+
readonly competition_id: string;
|
|
68
|
+
readonly sport_id: string;
|
|
69
|
+
readonly score_text: string;
|
|
70
|
+
readonly info: GameInfo | null;
|
|
71
|
+
readonly stats: GameStats | null;
|
|
72
|
+
readonly updated_at: string;
|
|
73
|
+
readonly markets: readonly Market[];
|
|
74
|
+
}
|
|
75
|
+
interface LiveSnapshot {
|
|
76
|
+
readonly sports: readonly SportCount[];
|
|
77
|
+
readonly games: readonly Game[];
|
|
78
|
+
}
|
|
79
|
+
interface OddsSummary {
|
|
80
|
+
readonly event_id: string;
|
|
81
|
+
readonly event_name: string;
|
|
82
|
+
readonly current_price: number;
|
|
83
|
+
readonly min_price: number;
|
|
84
|
+
readonly max_price: number;
|
|
85
|
+
readonly avg_price: number;
|
|
86
|
+
readonly change_count: number;
|
|
87
|
+
}
|
|
88
|
+
interface OddsMover {
|
|
89
|
+
readonly event_id: string;
|
|
90
|
+
readonly game_id: string;
|
|
91
|
+
readonly current_price: number;
|
|
92
|
+
readonly opening_price: number;
|
|
93
|
+
readonly price_change: number;
|
|
94
|
+
readonly change_percent: number;
|
|
95
|
+
readonly game_name: string;
|
|
96
|
+
readonly market_name: string;
|
|
97
|
+
readonly event_name: string;
|
|
98
|
+
}
|
|
99
|
+
interface PricePoint {
|
|
100
|
+
readonly price: number;
|
|
101
|
+
readonly previous_price: number;
|
|
102
|
+
readonly recorded_at: string;
|
|
103
|
+
}
|
|
104
|
+
type Plan = 'free' | 'starter' | 'pro' | 'business';
|
|
105
|
+
interface DebugConfig {
|
|
106
|
+
readonly host: string;
|
|
107
|
+
readonly secret: string;
|
|
108
|
+
readonly plan?: Plan;
|
|
109
|
+
}
|
|
110
|
+
interface ScorioSDKConfig {
|
|
111
|
+
readonly apiKey: string;
|
|
112
|
+
readonly host?: string;
|
|
113
|
+
readonly logger?: boolean;
|
|
114
|
+
readonly timeout?: number;
|
|
115
|
+
readonly debug?: DebugConfig;
|
|
116
|
+
}
|
|
117
|
+
interface PaginationOptions {
|
|
118
|
+
readonly limit?: number;
|
|
119
|
+
readonly offset?: number;
|
|
120
|
+
}
|
|
121
|
+
interface StartingSoonOptions {
|
|
122
|
+
readonly minutes?: number;
|
|
123
|
+
}
|
|
124
|
+
interface SearchOptions {
|
|
125
|
+
readonly limit?: number;
|
|
126
|
+
}
|
|
127
|
+
interface OddsMoversOptions {
|
|
128
|
+
readonly minutes?: number;
|
|
129
|
+
readonly limit?: number;
|
|
130
|
+
}
|
|
131
|
+
interface PriceHistoryOptions {
|
|
132
|
+
readonly from?: number;
|
|
133
|
+
readonly to?: number;
|
|
134
|
+
readonly limit?: number;
|
|
135
|
+
}
|
|
136
|
+
interface ScheduleOptions {
|
|
137
|
+
readonly date?: string;
|
|
138
|
+
readonly dateFrom?: string;
|
|
139
|
+
readonly dateTo?: string;
|
|
140
|
+
readonly sportId?: string;
|
|
141
|
+
readonly competitionId?: string;
|
|
142
|
+
}
|
|
143
|
+
interface HealthResponse {
|
|
144
|
+
readonly status: 'ok';
|
|
145
|
+
}
|
|
146
|
+
interface PingResponse {
|
|
147
|
+
readonly pong: true;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
interface HttpRequest {
|
|
151
|
+
readonly method: 'GET';
|
|
152
|
+
readonly url: string;
|
|
153
|
+
readonly headers: Record<string, string>;
|
|
154
|
+
readonly timeout: number;
|
|
155
|
+
}
|
|
156
|
+
interface HttpResponse {
|
|
157
|
+
readonly status: number;
|
|
158
|
+
readonly headers: {
|
|
159
|
+
get(name: string): string | null;
|
|
160
|
+
};
|
|
161
|
+
readonly json: () => Promise<unknown>;
|
|
162
|
+
}
|
|
163
|
+
interface HttpClientPort {
|
|
164
|
+
request(req: HttpRequest): Promise<HttpResponse>;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
declare class ScorioSDK {
|
|
168
|
+
private readonly apiKey;
|
|
169
|
+
private readonly host;
|
|
170
|
+
private readonly timeout;
|
|
171
|
+
private readonly logger;
|
|
172
|
+
private readonly config;
|
|
173
|
+
private readonly http;
|
|
174
|
+
constructor(config: ScorioSDKConfig, httpClient?: HttpClientPort);
|
|
175
|
+
private get;
|
|
176
|
+
/**
|
|
177
|
+
* List all available sports.
|
|
178
|
+
*
|
|
179
|
+
* Returns every available sport sorted by display order.
|
|
180
|
+
* Use this to build your top-level navigation or sport selector.
|
|
181
|
+
*
|
|
182
|
+
* @returns List of Sport objects with id, name, alias, and category.
|
|
183
|
+
*
|
|
184
|
+
* **Plans:** free, starter, pro, business | **Group:** catalog
|
|
185
|
+
*
|
|
186
|
+
* **Polling:** Cache locally for 60 seconds. The sport catalog changes infrequently.
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```ts
|
|
190
|
+
* const { data, meta } = await client.getSports();
|
|
191
|
+
* // data: [{ id, name, alias, category }, ...]
|
|
192
|
+
* // meta: { count: number }
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
getSports(): Promise<ListResponse<Sport>>;
|
|
196
|
+
/**
|
|
197
|
+
* Sports with live and prematch game counts.
|
|
198
|
+
*
|
|
199
|
+
* Returns all sports along with the number of currently live and upcoming prematch games for each.
|
|
200
|
+
* Perfect for sidebar badges, sport selector counts, or deciding which sport feeds to subscribe to.
|
|
201
|
+
*
|
|
202
|
+
* @returns List of SportCount objects (Sport + live_count + prematch_count).
|
|
203
|
+
*
|
|
204
|
+
* **Plans:** free, starter, pro, business | **Group:** catalog
|
|
205
|
+
*
|
|
206
|
+
* **Polling:** Every 10-30 seconds. Counts change as games go live or finish.
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```ts
|
|
210
|
+
* const { data } = await client.getSportsCounts();
|
|
211
|
+
* // data: [{ id, name, alias, category, live_count, prematch_count }, ...]
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
getSportsCounts(): Promise<ListResponse<SportCount>>;
|
|
215
|
+
/**
|
|
216
|
+
* List regions for a sport.
|
|
217
|
+
*
|
|
218
|
+
* Returns all regions (countries or geographic areas) that currently have active games for the specified sport.
|
|
219
|
+
* Build the second level of your navigation tree (e.g., England, Germany, Spain for Football).
|
|
220
|
+
*
|
|
221
|
+
* @param sportId - Unique sport identifier (ULID). Get IDs from {@link getSports}.
|
|
222
|
+
* @returns List of Region objects with id, name, alias, and sport_id.
|
|
223
|
+
*
|
|
224
|
+
* **Plans:** free, starter, pro, business | **Group:** catalog
|
|
225
|
+
*
|
|
226
|
+
* **Polling:** Cache locally for 60 seconds.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```ts
|
|
230
|
+
* const { data } = await client.getRegions('01KNSZTCFAHSBS092VMZS7PMCW');
|
|
231
|
+
* // data: [{ id, name, alias, sport_id }, ...]
|
|
232
|
+
* ```
|
|
233
|
+
*/
|
|
234
|
+
getRegions(sportId: string): Promise<ListResponse<Region>>;
|
|
235
|
+
/**
|
|
236
|
+
* List competitions for a region.
|
|
237
|
+
*
|
|
238
|
+
* Returns all competitions (leagues, tournaments, cups) within the specified region.
|
|
239
|
+
* Build the third level of your navigation tree (e.g., Premier League, Championship, FA Cup for England).
|
|
240
|
+
*
|
|
241
|
+
* @param regionId - Unique region identifier (ULID). Get IDs from {@link getRegions}.
|
|
242
|
+
* @returns List of Competition objects with id, name, region_id, and sport_id.
|
|
243
|
+
*
|
|
244
|
+
* **Plans:** free, starter, pro, business | **Group:** catalog
|
|
245
|
+
*
|
|
246
|
+
* **Polling:** Cache locally for 60 seconds.
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```ts
|
|
250
|
+
* const { data } = await client.getCompetitions('01JRQ00000ENGLAND0000001');
|
|
251
|
+
* // data: [{ id, name, region_id, sport_id }, ...]
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
254
|
+
getCompetitions(regionId: string): Promise<ListResponse<Competition>>;
|
|
255
|
+
/**
|
|
256
|
+
* List all competitions for a sport (flat list).
|
|
257
|
+
*
|
|
258
|
+
* Returns all competitions for the specified sport across ALL regions in one call.
|
|
259
|
+
* Useful for building flat competition selectors, search/filter dropdowns, or schedule filters.
|
|
260
|
+
*
|
|
261
|
+
* @param sportId - Unique sport identifier (ULID). Get IDs from {@link getSports}.
|
|
262
|
+
* @returns Flat list of Competition objects.
|
|
263
|
+
*
|
|
264
|
+
* **Plans:** free, starter, pro, business | **Group:** catalog
|
|
265
|
+
*
|
|
266
|
+
* **Polling:** Cache locally for 60 seconds.
|
|
267
|
+
*
|
|
268
|
+
* @example
|
|
269
|
+
* ```ts
|
|
270
|
+
* const { data } = await client.getCompetitionsBySport('01KNSZTCFAHSBS092VMZS7PMCW');
|
|
271
|
+
* // data: [{ id: "...", name: "Premier League", region_id, sport_id }, ...]
|
|
272
|
+
* ```
|
|
273
|
+
*/
|
|
274
|
+
getCompetitionsBySport(sportId: string): Promise<ListResponse<Competition>>;
|
|
275
|
+
/**
|
|
276
|
+
* All live games across all sports.
|
|
277
|
+
*
|
|
278
|
+
* Returns every currently live (in-play) game in a single call.
|
|
279
|
+
* Ideal for multi-sport live tickers, aggregate live feeds, or monitoring total live game volume.
|
|
280
|
+
*
|
|
281
|
+
* @returns List of Game objects with is_live: true, including scores, stats, and market counts.
|
|
282
|
+
*
|
|
283
|
+
* **Plans:** starter, pro, business | **Group:** live
|
|
284
|
+
*
|
|
285
|
+
* **Polling:** Every 1-2 seconds for real-time updates.
|
|
286
|
+
* At peak hours this can return 200+ games. If you only need one sport, use {@link getLiveGamesBySport}.
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```ts
|
|
290
|
+
* const { data } = await client.getAllLiveGames();
|
|
291
|
+
* // data: [{ id, home_team, away_team, status: "live", score_text, info, stats, ... }, ...]
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
getAllLiveGames(): Promise<ListResponse<Game>>;
|
|
295
|
+
/**
|
|
296
|
+
* Live games for a specific sport.
|
|
297
|
+
*
|
|
298
|
+
* Returns all currently live (in-play) games for the specified sport.
|
|
299
|
+
* More efficient than {@link getAllLiveGames} when you only need one sport.
|
|
300
|
+
*
|
|
301
|
+
* @param sportId - Unique sport identifier (ULID). Get IDs from {@link getSports}.
|
|
302
|
+
* @returns List of live Game objects filtered to the requested sport.
|
|
303
|
+
*
|
|
304
|
+
* **Plans:** starter, pro, business | **Group:** live
|
|
305
|
+
*
|
|
306
|
+
* **Polling:** Every 1-2 seconds for real-time updates.
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* ```ts
|
|
310
|
+
* const { data } = await client.getLiveGamesBySport('01KNSZTCFAHSBS092VMZS7PMCW');
|
|
311
|
+
* // data: [{ id, home_team, away_team, score_text: "2:1 (67')", ... }, ...]
|
|
312
|
+
* ```
|
|
313
|
+
*/
|
|
314
|
+
getLiveGamesBySport(sportId: string): Promise<ListResponse<Game>>;
|
|
315
|
+
/**
|
|
316
|
+
* Full live dashboard snapshot.
|
|
317
|
+
*
|
|
318
|
+
* Returns a complete live dashboard in a single API call: sport counts and all live games combined.
|
|
319
|
+
* Combines `/api/sports/counts` and `/api/live/games` to reduce round trips.
|
|
320
|
+
*
|
|
321
|
+
* @returns LiveSnapshot containing sports (with counts) and all live games.
|
|
322
|
+
*
|
|
323
|
+
* **Plans:** starter, pro, business | **Group:** live
|
|
324
|
+
*
|
|
325
|
+
* **Polling:** Every 2-5 seconds. This is a heavier endpoint.
|
|
326
|
+
* For granular updates after initial load, prefer individual endpoints.
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* ```ts
|
|
330
|
+
* const { data } = await client.getLiveSnapshot();
|
|
331
|
+
* // data: { sports: [{ id, name, live_count, prematch_count, ... }], games: [...] }
|
|
332
|
+
* ```
|
|
333
|
+
*/
|
|
334
|
+
getLiveSnapshot(): Promise<SingleResponse<LiveSnapshot>>;
|
|
335
|
+
/**
|
|
336
|
+
* Prematch games for a sport (paginated).
|
|
337
|
+
*
|
|
338
|
+
* Returns upcoming (prematch) games for the specified sport with pagination support.
|
|
339
|
+
* Sports like Football can have 1500+ prematch games.
|
|
340
|
+
*
|
|
341
|
+
* @param sportId - Unique sport identifier (ULID). Get IDs from {@link getSports}.
|
|
342
|
+
* @param options - Pagination options: limit (1-100, default 50) and offset (default 0).
|
|
343
|
+
* @returns Paginated list of prematch Game objects.
|
|
344
|
+
*
|
|
345
|
+
* **Plans:** starter, pro, business | **Group:** prematch
|
|
346
|
+
*
|
|
347
|
+
* **Polling:** Every 10-30 seconds. Prematch odds update less frequently than live.
|
|
348
|
+
*
|
|
349
|
+
* @example
|
|
350
|
+
* ```ts
|
|
351
|
+
* const { data, meta } = await client.getPrematchGames('01KNSZTCFAHSBS092VMZS7PMCW', { limit: 20 });
|
|
352
|
+
* // data: [{ id, home_team, away_team, status: "prematch", start_time, ... }, ...]
|
|
353
|
+
* ```
|
|
354
|
+
*/
|
|
355
|
+
getPrematchGames(sportId: string, options?: PaginationOptions): Promise<ListResponse<Game>>;
|
|
356
|
+
/**
|
|
357
|
+
* Games for a competition (paginated).
|
|
358
|
+
*
|
|
359
|
+
* Returns games for a specific competition with pagination.
|
|
360
|
+
* Includes games that have recently started (up to 2 hours ago) and all upcoming games.
|
|
361
|
+
*
|
|
362
|
+
* @param competitionId - Unique competition identifier (ULID). Get IDs from {@link getCompetitions} or {@link getCompetitionsBySport}.
|
|
363
|
+
* @param options - Pagination options: limit (1-100, default 50) and offset (default 0).
|
|
364
|
+
* @returns Paginated list of Game objects sorted by start time.
|
|
365
|
+
*
|
|
366
|
+
* **Plans:** starter, pro, business | **Group:** games
|
|
367
|
+
*
|
|
368
|
+
* **Polling:** Every 10-30 seconds for prematch, 1-2 seconds if showing live games.
|
|
369
|
+
*
|
|
370
|
+
* @example
|
|
371
|
+
* ```ts
|
|
372
|
+
* const { data } = await client.getGamesByCompetition('01KNSZTCFGMM6JE2B9YQFGQCDZ', { limit: 10 });
|
|
373
|
+
* ```
|
|
374
|
+
*/
|
|
375
|
+
getGamesByCompetition(competitionId: string, options?: PaginationOptions): Promise<ListResponse<Game>>;
|
|
376
|
+
/**
|
|
377
|
+
* Games starting within N minutes.
|
|
378
|
+
*
|
|
379
|
+
* Returns games that are about to start within the specified time window.
|
|
380
|
+
* Great for "Starting Soon" widgets or last-minute bet notifications.
|
|
381
|
+
*
|
|
382
|
+
* @param options - minutes: time window (1-180, default 30).
|
|
383
|
+
* @returns List of prematch Game objects sorted by start time (soonest first).
|
|
384
|
+
*
|
|
385
|
+
* **Plans:** starter, pro, business | **Group:** games
|
|
386
|
+
*
|
|
387
|
+
* **Polling:** Every 30-60 seconds.
|
|
388
|
+
*
|
|
389
|
+
* @example
|
|
390
|
+
* ```ts
|
|
391
|
+
* const { data } = await client.getGamesStartingSoon({ minutes: 60 });
|
|
392
|
+
* ```
|
|
393
|
+
*/
|
|
394
|
+
getGamesStartingSoon(options?: StartingSoonOptions): Promise<ListResponse<Game>>;
|
|
395
|
+
/**
|
|
396
|
+
* Search games by team name.
|
|
397
|
+
*
|
|
398
|
+
* Case-insensitive partial match against both home_team and away_team across all sports.
|
|
399
|
+
* Sorted by relevance, then by start time.
|
|
400
|
+
*
|
|
401
|
+
* @param query - Search query string (minimum 2 characters).
|
|
402
|
+
* @param options - limit: max results (1-50, default 20).
|
|
403
|
+
* @returns List of matching Game objects.
|
|
404
|
+
*
|
|
405
|
+
* **Plans:** starter, pro, business | **Group:** games
|
|
406
|
+
*
|
|
407
|
+
* **Polling:** On demand (triggered by user input).
|
|
408
|
+
*
|
|
409
|
+
* @example
|
|
410
|
+
* ```ts
|
|
411
|
+
* const { data } = await client.searchGames('Arsenal', { limit: 10 });
|
|
412
|
+
* ```
|
|
413
|
+
*/
|
|
414
|
+
searchGames(query: string, options?: SearchOptions): Promise<ListResponse<Game>>;
|
|
415
|
+
/**
|
|
416
|
+
* Full game detail with all markets and odds.
|
|
417
|
+
*
|
|
418
|
+
* Returns complete data for a single game: metadata, all markets, and all outcomes.
|
|
419
|
+
* Everything needed to render a full betting interface.
|
|
420
|
+
*
|
|
421
|
+
* @param gameId - Unique game identifier (ULID). Get IDs from any endpoint that returns Game objects.
|
|
422
|
+
* @returns Single Game object with nested markets and outcomes.
|
|
423
|
+
*
|
|
424
|
+
* **Plans:** starter, pro, business | **Group:** games
|
|
425
|
+
*
|
|
426
|
+
* Markets are populated only on **pro** and **business** plans.
|
|
427
|
+
* Lower plans receive `markets: []` and `markets_count: 0`.
|
|
428
|
+
*
|
|
429
|
+
* **Polling:** Every 1-2 seconds for live games, 10-30 seconds for prematch.
|
|
430
|
+
*
|
|
431
|
+
* @example
|
|
432
|
+
* ```ts
|
|
433
|
+
* const { data } = await client.getGameDetail('01TESTGAME00000LIVESOC01');
|
|
434
|
+
* // data.markets: [{ id, name, type, line, outcomes: [{ id, name, price, is_suspended }] }]
|
|
435
|
+
* ```
|
|
436
|
+
*/
|
|
437
|
+
getGameDetail(gameId: string): Promise<SingleResponse<Game>>;
|
|
438
|
+
/**
|
|
439
|
+
* Games by date or date range.
|
|
440
|
+
*
|
|
441
|
+
* Returns all games scheduled for a specific date or range, optionally filtered by sport or competition.
|
|
442
|
+
* Uses UTC dates. Defaults to today if no date params provided.
|
|
443
|
+
*
|
|
444
|
+
* @param options - date (YYYY-MM-DD), dateFrom/dateTo (max 90 days), sportId, competitionId.
|
|
445
|
+
* @returns List of Game objects sorted by start time.
|
|
446
|
+
*
|
|
447
|
+
* **Plans:** starter, pro, business | **Group:** schedule
|
|
448
|
+
*
|
|
449
|
+
* **Polling:** Every 60 seconds.
|
|
450
|
+
*
|
|
451
|
+
* @example
|
|
452
|
+
* ```ts
|
|
453
|
+
* const { data } = await client.getSchedule({ date: '2026-04-10', sportId: '01KNSZTCFAHSBS092VMZS7PMCW' });
|
|
454
|
+
* ```
|
|
455
|
+
*/
|
|
456
|
+
getSchedule(options?: ScheduleOptions): Promise<ListResponse<Game>>;
|
|
457
|
+
/**
|
|
458
|
+
* Min/max/avg price summary per outcome for a game.
|
|
459
|
+
*
|
|
460
|
+
* Returns statistical summary of odds for every outcome: min, max, average price, and number of changes.
|
|
461
|
+
* Useful for identifying value bets, overreactions, and market inefficiencies.
|
|
462
|
+
*
|
|
463
|
+
* @param gameId - Unique game identifier (ULID).
|
|
464
|
+
* @returns List of OddsSummary objects, one per outcome.
|
|
465
|
+
*
|
|
466
|
+
* **Plans:** pro, business | **Group:** odds
|
|
467
|
+
*
|
|
468
|
+
* **Polling:** Every 10-30 seconds.
|
|
469
|
+
*
|
|
470
|
+
* @example
|
|
471
|
+
* ```ts
|
|
472
|
+
* const { data } = await client.getGameOddsSummary('01TESTGAME00000LIVESOC01');
|
|
473
|
+
* // data: [{ event_id, event_name, current_price, min_price, max_price, avg_price, change_count }]
|
|
474
|
+
* ```
|
|
475
|
+
*/
|
|
476
|
+
getGameOddsSummary(gameId: string): Promise<ListResponse<OddsSummary>>;
|
|
477
|
+
/**
|
|
478
|
+
* Top odds movements (biggest price changes).
|
|
479
|
+
*
|
|
480
|
+
* Returns outcomes with the largest odds movements within a given time window.
|
|
481
|
+
* Key differentiator for professional bettors and odds aggregation platforms.
|
|
482
|
+
*
|
|
483
|
+
* @param options - minutes: look-back window (1-1440, default 60), limit: max results (1-100, default 20).
|
|
484
|
+
* @returns List of OddsMover objects sorted by absolute change percentage (largest first).
|
|
485
|
+
*
|
|
486
|
+
* **Plans:** pro, business | **Group:** odds
|
|
487
|
+
*
|
|
488
|
+
* **Polling:** Every 5-10 seconds for near-real-time steam move alerts.
|
|
489
|
+
*
|
|
490
|
+
* @example
|
|
491
|
+
* ```ts
|
|
492
|
+
* const { data } = await client.getOddsMovers({ minutes: 30, limit: 10 });
|
|
493
|
+
* // data: [{ event_id, game_id, current_price, opening_price, price_change, change_percent, ... }]
|
|
494
|
+
* ```
|
|
495
|
+
*/
|
|
496
|
+
getOddsMovers(options?: OddsMoversOptions): Promise<ListResponse<OddsMover>>;
|
|
497
|
+
/**
|
|
498
|
+
* Historical price changes for an outcome.
|
|
499
|
+
*
|
|
500
|
+
* Returns the full history of price changes for a specific outcome (selection).
|
|
501
|
+
* Build odds movement charts, sparklines, or trend analysis visualizations.
|
|
502
|
+
* 60-day retention, tick-level granularity.
|
|
503
|
+
*
|
|
504
|
+
* @param eventId - Unique outcome identifier (ULID). Get IDs from Game objects with markets.
|
|
505
|
+
* @param options - from/to (unix timestamps), limit (1-5000, default 500).
|
|
506
|
+
* @returns Chronological list of PricePoint objects (oldest first).
|
|
507
|
+
*
|
|
508
|
+
* **Plans:** pro, business | **Group:** odds
|
|
509
|
+
*
|
|
510
|
+
* **Polling:** On demand.
|
|
511
|
+
*
|
|
512
|
+
* @example
|
|
513
|
+
* ```ts
|
|
514
|
+
* const { data } = await client.getEventPriceHistory('01TESTEVT00000ARS0NAL01', { limit: 100 });
|
|
515
|
+
* // data: [{ price, previous_price, recorded_at }, ...]
|
|
516
|
+
* ```
|
|
517
|
+
*/
|
|
518
|
+
getEventPriceHistory(eventId: string, options?: PriceHistoryOptions): Promise<ListResponse<PricePoint>>;
|
|
519
|
+
/**
|
|
520
|
+
* Health check.
|
|
521
|
+
*
|
|
522
|
+
* Returns the current health status of the API. No authentication required.
|
|
523
|
+
* Use in load balancer health checks, uptime monitoring, or status pages.
|
|
524
|
+
*
|
|
525
|
+
* @returns `{ status: "ok" }` when the API is healthy.
|
|
526
|
+
*
|
|
527
|
+
* **Plans:** all (no authentication required) | **Group:** system
|
|
528
|
+
*
|
|
529
|
+
* **Polling:** Every 30-60 seconds from your monitoring system.
|
|
530
|
+
*/
|
|
531
|
+
health(): Promise<HealthResponse>;
|
|
532
|
+
/**
|
|
533
|
+
* Ping.
|
|
534
|
+
*
|
|
535
|
+
* Simple connectivity check. No authentication required.
|
|
536
|
+
* Quick liveness probe for monitoring or client-side connectivity checks.
|
|
537
|
+
*
|
|
538
|
+
* @returns `{ pong: true }`
|
|
539
|
+
*
|
|
540
|
+
* **Plans:** all (no authentication required) | **Group:** system
|
|
541
|
+
*/
|
|
542
|
+
ping(): Promise<PingResponse>;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
declare class ScorioError extends Error {
|
|
546
|
+
readonly status: number;
|
|
547
|
+
readonly code: string;
|
|
548
|
+
constructor(message: string, status: number, code: string);
|
|
549
|
+
}
|
|
550
|
+
declare class PlanLimitError extends ScorioError {
|
|
551
|
+
readonly currentPlan: string;
|
|
552
|
+
constructor(message: string, currentPlan: string);
|
|
553
|
+
}
|
|
554
|
+
declare class RateLimitError extends ScorioError {
|
|
555
|
+
readonly retryAfter: number;
|
|
556
|
+
constructor(message: string, retryAfter: number);
|
|
557
|
+
}
|
|
558
|
+
declare class NetworkError extends ScorioError {
|
|
559
|
+
constructor(message: string, options?: {
|
|
560
|
+
cause?: unknown;
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
export { type Competition, type DebugConfig, type Game, type GameInfo, type GameStats, type HealthResponse, type ListResponse, type LiveSnapshot, type Market, NetworkError, type OddsMover, type OddsMoversOptions, type OddsSummary, type Outcome, type PaginationOptions, type PingResponse, type Plan, PlanLimitError, type PriceHistoryOptions, type PricePoint, RateLimitError, type Region, type ScheduleOptions, ScorioError, type ScorioSDKConfig, type SearchOptions, type SingleResponse, type Sport, type SportCount, type StartingSoonOptions, ScorioSDK as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,623 @@
|
|
|
1
|
+
// src/domain/errors.ts
|
|
2
|
+
var ScorioError = class extends Error {
|
|
3
|
+
status;
|
|
4
|
+
code;
|
|
5
|
+
constructor(message, status, code) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "ScorioError";
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.code = code;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
var PlanLimitError = class extends ScorioError {
|
|
13
|
+
currentPlan;
|
|
14
|
+
constructor(message, currentPlan) {
|
|
15
|
+
super(message, 403, "plan_limit");
|
|
16
|
+
this.name = "PlanLimitError";
|
|
17
|
+
this.currentPlan = currentPlan;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
var RateLimitError = class extends ScorioError {
|
|
21
|
+
retryAfter;
|
|
22
|
+
constructor(message, retryAfter) {
|
|
23
|
+
super(message, 429, "rate_limit");
|
|
24
|
+
this.name = "RateLimitError";
|
|
25
|
+
this.retryAfter = retryAfter;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
var NetworkError = class extends ScorioError {
|
|
29
|
+
constructor(message, options) {
|
|
30
|
+
super(message, 0, "network_error");
|
|
31
|
+
this.name = "NetworkError";
|
|
32
|
+
if (options?.cause) {
|
|
33
|
+
this.cause = options.cause;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// src/infrastructure/http/error-mapper.ts
|
|
39
|
+
function isErrorBody(body) {
|
|
40
|
+
return typeof body === "object" && body !== null && "error" in body;
|
|
41
|
+
}
|
|
42
|
+
function extractMessage(body) {
|
|
43
|
+
if (isErrorBody(body)) {
|
|
44
|
+
return body.message ?? body.error ?? "Unknown error";
|
|
45
|
+
}
|
|
46
|
+
return "Unknown error";
|
|
47
|
+
}
|
|
48
|
+
function extractPlan(body) {
|
|
49
|
+
if (isErrorBody(body) && typeof body.message === "string") {
|
|
50
|
+
const match = body.message.match(/Current plan: (\w+)/);
|
|
51
|
+
if (match?.[1]) return match[1];
|
|
52
|
+
}
|
|
53
|
+
return "unknown";
|
|
54
|
+
}
|
|
55
|
+
async function mapResponseToError(status, headers, jsonFn) {
|
|
56
|
+
let body;
|
|
57
|
+
try {
|
|
58
|
+
body = await jsonFn();
|
|
59
|
+
} catch {
|
|
60
|
+
body = null;
|
|
61
|
+
}
|
|
62
|
+
const message = extractMessage(body);
|
|
63
|
+
if (status === 403 && isErrorBody(body) && body.error === "plan_limit") {
|
|
64
|
+
return new PlanLimitError(message, extractPlan(body));
|
|
65
|
+
}
|
|
66
|
+
if (status === 429) {
|
|
67
|
+
const retryAfter = Number(headers.get("retry-after") ?? "1");
|
|
68
|
+
return new RateLimitError(message, retryAfter);
|
|
69
|
+
}
|
|
70
|
+
return new ScorioError(message, status, "api_error");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/infrastructure/http/fetch-client.ts
|
|
74
|
+
var FetchHttpClient = class {
|
|
75
|
+
async request(req) {
|
|
76
|
+
try {
|
|
77
|
+
const response = await fetch(req.url, {
|
|
78
|
+
method: req.method,
|
|
79
|
+
headers: req.headers,
|
|
80
|
+
signal: AbortSignal.timeout(req.timeout)
|
|
81
|
+
});
|
|
82
|
+
return {
|
|
83
|
+
status: response.status,
|
|
84
|
+
headers: response.headers,
|
|
85
|
+
json: () => response.json()
|
|
86
|
+
};
|
|
87
|
+
} catch (error) {
|
|
88
|
+
if (error instanceof DOMException && error.name === "TimeoutError") {
|
|
89
|
+
throw new NetworkError(`Request timed out after ${req.timeout}ms`);
|
|
90
|
+
}
|
|
91
|
+
if (error instanceof TypeError) {
|
|
92
|
+
throw new NetworkError("Network request failed", { cause: error });
|
|
93
|
+
}
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// src/infrastructure/http/headers.ts
|
|
100
|
+
var PLAN_TO_HEADER = {
|
|
101
|
+
free: "BASIC",
|
|
102
|
+
starter: "STARTER",
|
|
103
|
+
pro: "ULTRA",
|
|
104
|
+
business: "MEGA"
|
|
105
|
+
};
|
|
106
|
+
function buildHeaders(apiKey, host, debug, isSystem) {
|
|
107
|
+
const headers = {
|
|
108
|
+
Accept: "application/json"
|
|
109
|
+
};
|
|
110
|
+
if (isSystem) return headers;
|
|
111
|
+
if (debug) {
|
|
112
|
+
headers["x-rapidapi-proxy-secret"] = debug.secret;
|
|
113
|
+
if (debug.plan) {
|
|
114
|
+
headers["x-rapidapi-subscription"] = PLAN_TO_HEADER[debug.plan];
|
|
115
|
+
}
|
|
116
|
+
} else {
|
|
117
|
+
headers["X-RapidAPI-Key"] = apiKey;
|
|
118
|
+
headers["X-RapidAPI-Host"] = host;
|
|
119
|
+
}
|
|
120
|
+
return headers;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// src/infrastructure/http/url-builder.ts
|
|
124
|
+
function serializeParams(params) {
|
|
125
|
+
if (!params) return "";
|
|
126
|
+
const entries = [];
|
|
127
|
+
for (const [k, v] of Object.entries(params)) {
|
|
128
|
+
if (v !== void 0 && v !== null && v !== "") {
|
|
129
|
+
entries.push(`${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return entries.join("&");
|
|
133
|
+
}
|
|
134
|
+
function buildUrl(host, path, params) {
|
|
135
|
+
const base = `https://${host}${path}`;
|
|
136
|
+
const search = serializeParams(params);
|
|
137
|
+
return search ? `${base}?${search}` : base;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// src/application/sdk.ts
|
|
141
|
+
var ScorioSDK = class {
|
|
142
|
+
apiKey;
|
|
143
|
+
host;
|
|
144
|
+
timeout;
|
|
145
|
+
logger;
|
|
146
|
+
config;
|
|
147
|
+
http;
|
|
148
|
+
constructor(config, httpClient) {
|
|
149
|
+
if (!config.apiKey) {
|
|
150
|
+
throw new Error("apiKey is required");
|
|
151
|
+
}
|
|
152
|
+
this.apiKey = config.apiKey;
|
|
153
|
+
this.host = config.debug?.host ?? config.host ?? "";
|
|
154
|
+
this.timeout = config.timeout ?? 3e4;
|
|
155
|
+
this.logger = config.logger ?? false;
|
|
156
|
+
this.config = config;
|
|
157
|
+
this.http = httpClient ?? new FetchHttpClient();
|
|
158
|
+
if (!this.host) {
|
|
159
|
+
throw new Error("host is required (or provide debug.host)");
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async get(path, params, isSystem = false) {
|
|
163
|
+
const url = buildUrl(this.host, path, params);
|
|
164
|
+
const headers = buildHeaders(this.apiKey, this.host, this.config.debug, isSystem);
|
|
165
|
+
if (this.logger) {
|
|
166
|
+
console.log(`[scorio-sdk] GET ${path}`);
|
|
167
|
+
}
|
|
168
|
+
const response = await this.http.request({
|
|
169
|
+
method: "GET",
|
|
170
|
+
url,
|
|
171
|
+
headers,
|
|
172
|
+
timeout: this.timeout
|
|
173
|
+
});
|
|
174
|
+
if (response.status < 200 || response.status >= 300) {
|
|
175
|
+
throw await mapResponseToError(response.status, response.headers, response.json);
|
|
176
|
+
}
|
|
177
|
+
return response.json();
|
|
178
|
+
}
|
|
179
|
+
// ─── Catalog ───────────────────────────────────────────────────
|
|
180
|
+
/**
|
|
181
|
+
* List all available sports.
|
|
182
|
+
*
|
|
183
|
+
* Returns every available sport sorted by display order.
|
|
184
|
+
* Use this to build your top-level navigation or sport selector.
|
|
185
|
+
*
|
|
186
|
+
* @returns List of Sport objects with id, name, alias, and category.
|
|
187
|
+
*
|
|
188
|
+
* **Plans:** free, starter, pro, business | **Group:** catalog
|
|
189
|
+
*
|
|
190
|
+
* **Polling:** Cache locally for 60 seconds. The sport catalog changes infrequently.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```ts
|
|
194
|
+
* const { data, meta } = await client.getSports();
|
|
195
|
+
* // data: [{ id, name, alias, category }, ...]
|
|
196
|
+
* // meta: { count: number }
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
async getSports() {
|
|
200
|
+
return this.get("/api/sports");
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Sports with live and prematch game counts.
|
|
204
|
+
*
|
|
205
|
+
* Returns all sports along with the number of currently live and upcoming prematch games for each.
|
|
206
|
+
* Perfect for sidebar badges, sport selector counts, or deciding which sport feeds to subscribe to.
|
|
207
|
+
*
|
|
208
|
+
* @returns List of SportCount objects (Sport + live_count + prematch_count).
|
|
209
|
+
*
|
|
210
|
+
* **Plans:** free, starter, pro, business | **Group:** catalog
|
|
211
|
+
*
|
|
212
|
+
* **Polling:** Every 10-30 seconds. Counts change as games go live or finish.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```ts
|
|
216
|
+
* const { data } = await client.getSportsCounts();
|
|
217
|
+
* // data: [{ id, name, alias, category, live_count, prematch_count }, ...]
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
async getSportsCounts() {
|
|
221
|
+
return this.get("/api/sports/counts");
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* List regions for a sport.
|
|
225
|
+
*
|
|
226
|
+
* Returns all regions (countries or geographic areas) that currently have active games for the specified sport.
|
|
227
|
+
* Build the second level of your navigation tree (e.g., England, Germany, Spain for Football).
|
|
228
|
+
*
|
|
229
|
+
* @param sportId - Unique sport identifier (ULID). Get IDs from {@link getSports}.
|
|
230
|
+
* @returns List of Region objects with id, name, alias, and sport_id.
|
|
231
|
+
*
|
|
232
|
+
* **Plans:** free, starter, pro, business | **Group:** catalog
|
|
233
|
+
*
|
|
234
|
+
* **Polling:** Cache locally for 60 seconds.
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```ts
|
|
238
|
+
* const { data } = await client.getRegions('01KNSZTCFAHSBS092VMZS7PMCW');
|
|
239
|
+
* // data: [{ id, name, alias, sport_id }, ...]
|
|
240
|
+
* ```
|
|
241
|
+
*/
|
|
242
|
+
async getRegions(sportId) {
|
|
243
|
+
return this.get(`/api/sports/${sportId}/regions`);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* List competitions for a region.
|
|
247
|
+
*
|
|
248
|
+
* Returns all competitions (leagues, tournaments, cups) within the specified region.
|
|
249
|
+
* Build the third level of your navigation tree (e.g., Premier League, Championship, FA Cup for England).
|
|
250
|
+
*
|
|
251
|
+
* @param regionId - Unique region identifier (ULID). Get IDs from {@link getRegions}.
|
|
252
|
+
* @returns List of Competition objects with id, name, region_id, and sport_id.
|
|
253
|
+
*
|
|
254
|
+
* **Plans:** free, starter, pro, business | **Group:** catalog
|
|
255
|
+
*
|
|
256
|
+
* **Polling:** Cache locally for 60 seconds.
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```ts
|
|
260
|
+
* const { data } = await client.getCompetitions('01JRQ00000ENGLAND0000001');
|
|
261
|
+
* // data: [{ id, name, region_id, sport_id }, ...]
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
async getCompetitions(regionId) {
|
|
265
|
+
return this.get(`/api/regions/${regionId}/competitions`);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* List all competitions for a sport (flat list).
|
|
269
|
+
*
|
|
270
|
+
* Returns all competitions for the specified sport across ALL regions in one call.
|
|
271
|
+
* Useful for building flat competition selectors, search/filter dropdowns, or schedule filters.
|
|
272
|
+
*
|
|
273
|
+
* @param sportId - Unique sport identifier (ULID). Get IDs from {@link getSports}.
|
|
274
|
+
* @returns Flat list of Competition objects.
|
|
275
|
+
*
|
|
276
|
+
* **Plans:** free, starter, pro, business | **Group:** catalog
|
|
277
|
+
*
|
|
278
|
+
* **Polling:** Cache locally for 60 seconds.
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* ```ts
|
|
282
|
+
* const { data } = await client.getCompetitionsBySport('01KNSZTCFAHSBS092VMZS7PMCW');
|
|
283
|
+
* // data: [{ id: "...", name: "Premier League", region_id, sport_id }, ...]
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
286
|
+
async getCompetitionsBySport(sportId) {
|
|
287
|
+
return this.get(`/api/sports/${sportId}/competitions`);
|
|
288
|
+
}
|
|
289
|
+
// ─── Live ──────────────────────────────────────────────────────
|
|
290
|
+
/**
|
|
291
|
+
* All live games across all sports.
|
|
292
|
+
*
|
|
293
|
+
* Returns every currently live (in-play) game in a single call.
|
|
294
|
+
* Ideal for multi-sport live tickers, aggregate live feeds, or monitoring total live game volume.
|
|
295
|
+
*
|
|
296
|
+
* @returns List of Game objects with is_live: true, including scores, stats, and market counts.
|
|
297
|
+
*
|
|
298
|
+
* **Plans:** starter, pro, business | **Group:** live
|
|
299
|
+
*
|
|
300
|
+
* **Polling:** Every 1-2 seconds for real-time updates.
|
|
301
|
+
* At peak hours this can return 200+ games. If you only need one sport, use {@link getLiveGamesBySport}.
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* ```ts
|
|
305
|
+
* const { data } = await client.getAllLiveGames();
|
|
306
|
+
* // data: [{ id, home_team, away_team, status: "live", score_text, info, stats, ... }, ...]
|
|
307
|
+
* ```
|
|
308
|
+
*/
|
|
309
|
+
async getAllLiveGames() {
|
|
310
|
+
return this.get("/api/live/games");
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Live games for a specific sport.
|
|
314
|
+
*
|
|
315
|
+
* Returns all currently live (in-play) games for the specified sport.
|
|
316
|
+
* More efficient than {@link getAllLiveGames} when you only need one sport.
|
|
317
|
+
*
|
|
318
|
+
* @param sportId - Unique sport identifier (ULID). Get IDs from {@link getSports}.
|
|
319
|
+
* @returns List of live Game objects filtered to the requested sport.
|
|
320
|
+
*
|
|
321
|
+
* **Plans:** starter, pro, business | **Group:** live
|
|
322
|
+
*
|
|
323
|
+
* **Polling:** Every 1-2 seconds for real-time updates.
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* ```ts
|
|
327
|
+
* const { data } = await client.getLiveGamesBySport('01KNSZTCFAHSBS092VMZS7PMCW');
|
|
328
|
+
* // data: [{ id, home_team, away_team, score_text: "2:1 (67')", ... }, ...]
|
|
329
|
+
* ```
|
|
330
|
+
*/
|
|
331
|
+
async getLiveGamesBySport(sportId) {
|
|
332
|
+
return this.get(`/api/live/games/${sportId}`);
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Full live dashboard snapshot.
|
|
336
|
+
*
|
|
337
|
+
* Returns a complete live dashboard in a single API call: sport counts and all live games combined.
|
|
338
|
+
* Combines `/api/sports/counts` and `/api/live/games` to reduce round trips.
|
|
339
|
+
*
|
|
340
|
+
* @returns LiveSnapshot containing sports (with counts) and all live games.
|
|
341
|
+
*
|
|
342
|
+
* **Plans:** starter, pro, business | **Group:** live
|
|
343
|
+
*
|
|
344
|
+
* **Polling:** Every 2-5 seconds. This is a heavier endpoint.
|
|
345
|
+
* For granular updates after initial load, prefer individual endpoints.
|
|
346
|
+
*
|
|
347
|
+
* @example
|
|
348
|
+
* ```ts
|
|
349
|
+
* const { data } = await client.getLiveSnapshot();
|
|
350
|
+
* // data: { sports: [{ id, name, live_count, prematch_count, ... }], games: [...] }
|
|
351
|
+
* ```
|
|
352
|
+
*/
|
|
353
|
+
async getLiveSnapshot() {
|
|
354
|
+
return this.get("/api/live/snapshot");
|
|
355
|
+
}
|
|
356
|
+
// ─── Prematch ──────────────────────────────────────────────────
|
|
357
|
+
/**
|
|
358
|
+
* Prematch games for a sport (paginated).
|
|
359
|
+
*
|
|
360
|
+
* Returns upcoming (prematch) games for the specified sport with pagination support.
|
|
361
|
+
* Sports like Football can have 1500+ prematch games.
|
|
362
|
+
*
|
|
363
|
+
* @param sportId - Unique sport identifier (ULID). Get IDs from {@link getSports}.
|
|
364
|
+
* @param options - Pagination options: limit (1-100, default 50) and offset (default 0).
|
|
365
|
+
* @returns Paginated list of prematch Game objects.
|
|
366
|
+
*
|
|
367
|
+
* **Plans:** starter, pro, business | **Group:** prematch
|
|
368
|
+
*
|
|
369
|
+
* **Polling:** Every 10-30 seconds. Prematch odds update less frequently than live.
|
|
370
|
+
*
|
|
371
|
+
* @example
|
|
372
|
+
* ```ts
|
|
373
|
+
* const { data, meta } = await client.getPrematchGames('01KNSZTCFAHSBS092VMZS7PMCW', { limit: 20 });
|
|
374
|
+
* // data: [{ id, home_team, away_team, status: "prematch", start_time, ... }, ...]
|
|
375
|
+
* ```
|
|
376
|
+
*/
|
|
377
|
+
async getPrematchGames(sportId, options) {
|
|
378
|
+
return this.get(`/api/prematch/games/${sportId}`, {
|
|
379
|
+
limit: options?.limit,
|
|
380
|
+
offset: options?.offset
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
// ─── Games ─────────────────────────────────────────────────────
|
|
384
|
+
/**
|
|
385
|
+
* Games for a competition (paginated).
|
|
386
|
+
*
|
|
387
|
+
* Returns games for a specific competition with pagination.
|
|
388
|
+
* Includes games that have recently started (up to 2 hours ago) and all upcoming games.
|
|
389
|
+
*
|
|
390
|
+
* @param competitionId - Unique competition identifier (ULID). Get IDs from {@link getCompetitions} or {@link getCompetitionsBySport}.
|
|
391
|
+
* @param options - Pagination options: limit (1-100, default 50) and offset (default 0).
|
|
392
|
+
* @returns Paginated list of Game objects sorted by start time.
|
|
393
|
+
*
|
|
394
|
+
* **Plans:** starter, pro, business | **Group:** games
|
|
395
|
+
*
|
|
396
|
+
* **Polling:** Every 10-30 seconds for prematch, 1-2 seconds if showing live games.
|
|
397
|
+
*
|
|
398
|
+
* @example
|
|
399
|
+
* ```ts
|
|
400
|
+
* const { data } = await client.getGamesByCompetition('01KNSZTCFGMM6JE2B9YQFGQCDZ', { limit: 10 });
|
|
401
|
+
* ```
|
|
402
|
+
*/
|
|
403
|
+
async getGamesByCompetition(competitionId, options) {
|
|
404
|
+
return this.get(`/api/competitions/${competitionId}/games`, {
|
|
405
|
+
limit: options?.limit,
|
|
406
|
+
offset: options?.offset
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Games starting within N minutes.
|
|
411
|
+
*
|
|
412
|
+
* Returns games that are about to start within the specified time window.
|
|
413
|
+
* Great for "Starting Soon" widgets or last-minute bet notifications.
|
|
414
|
+
*
|
|
415
|
+
* @param options - minutes: time window (1-180, default 30).
|
|
416
|
+
* @returns List of prematch Game objects sorted by start time (soonest first).
|
|
417
|
+
*
|
|
418
|
+
* **Plans:** starter, pro, business | **Group:** games
|
|
419
|
+
*
|
|
420
|
+
* **Polling:** Every 30-60 seconds.
|
|
421
|
+
*
|
|
422
|
+
* @example
|
|
423
|
+
* ```ts
|
|
424
|
+
* const { data } = await client.getGamesStartingSoon({ minutes: 60 });
|
|
425
|
+
* ```
|
|
426
|
+
*/
|
|
427
|
+
async getGamesStartingSoon(options) {
|
|
428
|
+
return this.get("/api/games/starting-soon", {
|
|
429
|
+
minutes: options?.minutes
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Search games by team name.
|
|
434
|
+
*
|
|
435
|
+
* Case-insensitive partial match against both home_team and away_team across all sports.
|
|
436
|
+
* Sorted by relevance, then by start time.
|
|
437
|
+
*
|
|
438
|
+
* @param query - Search query string (minimum 2 characters).
|
|
439
|
+
* @param options - limit: max results (1-50, default 20).
|
|
440
|
+
* @returns List of matching Game objects.
|
|
441
|
+
*
|
|
442
|
+
* **Plans:** starter, pro, business | **Group:** games
|
|
443
|
+
*
|
|
444
|
+
* **Polling:** On demand (triggered by user input).
|
|
445
|
+
*
|
|
446
|
+
* @example
|
|
447
|
+
* ```ts
|
|
448
|
+
* const { data } = await client.searchGames('Arsenal', { limit: 10 });
|
|
449
|
+
* ```
|
|
450
|
+
*/
|
|
451
|
+
async searchGames(query, options) {
|
|
452
|
+
return this.get("/api/games/search", {
|
|
453
|
+
q: query,
|
|
454
|
+
limit: options?.limit
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Full game detail with all markets and odds.
|
|
459
|
+
*
|
|
460
|
+
* Returns complete data for a single game: metadata, all markets, and all outcomes.
|
|
461
|
+
* Everything needed to render a full betting interface.
|
|
462
|
+
*
|
|
463
|
+
* @param gameId - Unique game identifier (ULID). Get IDs from any endpoint that returns Game objects.
|
|
464
|
+
* @returns Single Game object with nested markets and outcomes.
|
|
465
|
+
*
|
|
466
|
+
* **Plans:** starter, pro, business | **Group:** games
|
|
467
|
+
*
|
|
468
|
+
* Markets are populated only on **pro** and **business** plans.
|
|
469
|
+
* Lower plans receive `markets: []` and `markets_count: 0`.
|
|
470
|
+
*
|
|
471
|
+
* **Polling:** Every 1-2 seconds for live games, 10-30 seconds for prematch.
|
|
472
|
+
*
|
|
473
|
+
* @example
|
|
474
|
+
* ```ts
|
|
475
|
+
* const { data } = await client.getGameDetail('01TESTGAME00000LIVESOC01');
|
|
476
|
+
* // data.markets: [{ id, name, type, line, outcomes: [{ id, name, price, is_suspended }] }]
|
|
477
|
+
* ```
|
|
478
|
+
*/
|
|
479
|
+
async getGameDetail(gameId) {
|
|
480
|
+
return this.get(`/api/games/${gameId}`);
|
|
481
|
+
}
|
|
482
|
+
// ─── Schedule ──────────────────────────────────────────────────
|
|
483
|
+
/**
|
|
484
|
+
* Games by date or date range.
|
|
485
|
+
*
|
|
486
|
+
* Returns all games scheduled for a specific date or range, optionally filtered by sport or competition.
|
|
487
|
+
* Uses UTC dates. Defaults to today if no date params provided.
|
|
488
|
+
*
|
|
489
|
+
* @param options - date (YYYY-MM-DD), dateFrom/dateTo (max 90 days), sportId, competitionId.
|
|
490
|
+
* @returns List of Game objects sorted by start time.
|
|
491
|
+
*
|
|
492
|
+
* **Plans:** starter, pro, business | **Group:** schedule
|
|
493
|
+
*
|
|
494
|
+
* **Polling:** Every 60 seconds.
|
|
495
|
+
*
|
|
496
|
+
* @example
|
|
497
|
+
* ```ts
|
|
498
|
+
* const { data } = await client.getSchedule({ date: '2026-04-10', sportId: '01KNSZTCFAHSBS092VMZS7PMCW' });
|
|
499
|
+
* ```
|
|
500
|
+
*/
|
|
501
|
+
async getSchedule(options) {
|
|
502
|
+
return this.get("/api/schedule", {
|
|
503
|
+
date: options?.date,
|
|
504
|
+
date_from: options?.dateFrom,
|
|
505
|
+
date_to: options?.dateTo,
|
|
506
|
+
sport_id: options?.sportId,
|
|
507
|
+
competition_id: options?.competitionId
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
// ─── Odds Intelligence ─────────────────────────────────────────
|
|
511
|
+
/**
|
|
512
|
+
* Min/max/avg price summary per outcome for a game.
|
|
513
|
+
*
|
|
514
|
+
* Returns statistical summary of odds for every outcome: min, max, average price, and number of changes.
|
|
515
|
+
* Useful for identifying value bets, overreactions, and market inefficiencies.
|
|
516
|
+
*
|
|
517
|
+
* @param gameId - Unique game identifier (ULID).
|
|
518
|
+
* @returns List of OddsSummary objects, one per outcome.
|
|
519
|
+
*
|
|
520
|
+
* **Plans:** pro, business | **Group:** odds
|
|
521
|
+
*
|
|
522
|
+
* **Polling:** Every 10-30 seconds.
|
|
523
|
+
*
|
|
524
|
+
* @example
|
|
525
|
+
* ```ts
|
|
526
|
+
* const { data } = await client.getGameOddsSummary('01TESTGAME00000LIVESOC01');
|
|
527
|
+
* // data: [{ event_id, event_name, current_price, min_price, max_price, avg_price, change_count }]
|
|
528
|
+
* ```
|
|
529
|
+
*/
|
|
530
|
+
async getGameOddsSummary(gameId) {
|
|
531
|
+
return this.get(`/api/games/${gameId}/odds-summary`);
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Top odds movements (biggest price changes).
|
|
535
|
+
*
|
|
536
|
+
* Returns outcomes with the largest odds movements within a given time window.
|
|
537
|
+
* Key differentiator for professional bettors and odds aggregation platforms.
|
|
538
|
+
*
|
|
539
|
+
* @param options - minutes: look-back window (1-1440, default 60), limit: max results (1-100, default 20).
|
|
540
|
+
* @returns List of OddsMover objects sorted by absolute change percentage (largest first).
|
|
541
|
+
*
|
|
542
|
+
* **Plans:** pro, business | **Group:** odds
|
|
543
|
+
*
|
|
544
|
+
* **Polling:** Every 5-10 seconds for near-real-time steam move alerts.
|
|
545
|
+
*
|
|
546
|
+
* @example
|
|
547
|
+
* ```ts
|
|
548
|
+
* const { data } = await client.getOddsMovers({ minutes: 30, limit: 10 });
|
|
549
|
+
* // data: [{ event_id, game_id, current_price, opening_price, price_change, change_percent, ... }]
|
|
550
|
+
* ```
|
|
551
|
+
*/
|
|
552
|
+
async getOddsMovers(options) {
|
|
553
|
+
return this.get("/api/odds/movers", {
|
|
554
|
+
minutes: options?.minutes,
|
|
555
|
+
limit: options?.limit
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Historical price changes for an outcome.
|
|
560
|
+
*
|
|
561
|
+
* Returns the full history of price changes for a specific outcome (selection).
|
|
562
|
+
* Build odds movement charts, sparklines, or trend analysis visualizations.
|
|
563
|
+
* 60-day retention, tick-level granularity.
|
|
564
|
+
*
|
|
565
|
+
* @param eventId - Unique outcome identifier (ULID). Get IDs from Game objects with markets.
|
|
566
|
+
* @param options - from/to (unix timestamps), limit (1-5000, default 500).
|
|
567
|
+
* @returns Chronological list of PricePoint objects (oldest first).
|
|
568
|
+
*
|
|
569
|
+
* **Plans:** pro, business | **Group:** odds
|
|
570
|
+
*
|
|
571
|
+
* **Polling:** On demand.
|
|
572
|
+
*
|
|
573
|
+
* @example
|
|
574
|
+
* ```ts
|
|
575
|
+
* const { data } = await client.getEventPriceHistory('01TESTEVT00000ARS0NAL01', { limit: 100 });
|
|
576
|
+
* // data: [{ price, previous_price, recorded_at }, ...]
|
|
577
|
+
* ```
|
|
578
|
+
*/
|
|
579
|
+
async getEventPriceHistory(eventId, options) {
|
|
580
|
+
return this.get(`/api/events/${eventId}/price-history`, {
|
|
581
|
+
from: options?.from,
|
|
582
|
+
to: options?.to,
|
|
583
|
+
limit: options?.limit
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
// ─── System ────────────────────────────────────────────────────
|
|
587
|
+
/**
|
|
588
|
+
* Health check.
|
|
589
|
+
*
|
|
590
|
+
* Returns the current health status of the API. No authentication required.
|
|
591
|
+
* Use in load balancer health checks, uptime monitoring, or status pages.
|
|
592
|
+
*
|
|
593
|
+
* @returns `{ status: "ok" }` when the API is healthy.
|
|
594
|
+
*
|
|
595
|
+
* **Plans:** all (no authentication required) | **Group:** system
|
|
596
|
+
*
|
|
597
|
+
* **Polling:** Every 30-60 seconds from your monitoring system.
|
|
598
|
+
*/
|
|
599
|
+
async health() {
|
|
600
|
+
return this.get("/api/health", void 0, true);
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Ping.
|
|
604
|
+
*
|
|
605
|
+
* Simple connectivity check. No authentication required.
|
|
606
|
+
* Quick liveness probe for monitoring or client-side connectivity checks.
|
|
607
|
+
*
|
|
608
|
+
* @returns `{ pong: true }`
|
|
609
|
+
*
|
|
610
|
+
* **Plans:** all (no authentication required) | **Group:** system
|
|
611
|
+
*/
|
|
612
|
+
async ping() {
|
|
613
|
+
return this.get("/api/ping", void 0, true);
|
|
614
|
+
}
|
|
615
|
+
};
|
|
616
|
+
export {
|
|
617
|
+
NetworkError,
|
|
618
|
+
PlanLimitError,
|
|
619
|
+
RateLimitError,
|
|
620
|
+
ScorioError,
|
|
621
|
+
ScorioSDK as default
|
|
622
|
+
};
|
|
623
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/domain/errors.ts","../src/infrastructure/http/error-mapper.ts","../src/infrastructure/http/fetch-client.ts","../src/infrastructure/http/headers.ts","../src/infrastructure/http/url-builder.ts","../src/application/sdk.ts"],"sourcesContent":["export class ScorioError extends Error {\n\treadonly status: number;\n\treadonly code: string;\n\n\tconstructor(message: string, status: number, code: string) {\n\t\tsuper(message);\n\t\tthis.name = 'ScorioError';\n\t\tthis.status = status;\n\t\tthis.code = code;\n\t}\n}\n\nexport class PlanLimitError extends ScorioError {\n\treadonly currentPlan: string;\n\n\tconstructor(message: string, currentPlan: string) {\n\t\tsuper(message, 403, 'plan_limit');\n\t\tthis.name = 'PlanLimitError';\n\t\tthis.currentPlan = currentPlan;\n\t}\n}\n\nexport class RateLimitError extends ScorioError {\n\treadonly retryAfter: number;\n\n\tconstructor(message: string, retryAfter: number) {\n\t\tsuper(message, 429, 'rate_limit');\n\t\tthis.name = 'RateLimitError';\n\t\tthis.retryAfter = retryAfter;\n\t}\n}\n\nexport class NetworkError extends ScorioError {\n\tconstructor(message: string, options?: { cause?: unknown }) {\n\t\tsuper(message, 0, 'network_error');\n\t\tthis.name = 'NetworkError';\n\t\tif (options?.cause) {\n\t\t\tthis.cause = options.cause;\n\t\t}\n\t}\n}\n","import { NetworkError, PlanLimitError, RateLimitError, ScorioError } from '../../domain/errors.js';\n\ninterface ErrorBody {\n\terror?: string;\n\tmessage?: string;\n}\n\nfunction isErrorBody(body: unknown): body is ErrorBody {\n\treturn typeof body === 'object' && body !== null && 'error' in body;\n}\n\nfunction extractMessage(body: unknown): string {\n\tif (isErrorBody(body)) {\n\t\treturn body.message ?? body.error ?? 'Unknown error';\n\t}\n\treturn 'Unknown error';\n}\n\nfunction extractPlan(body: unknown): string {\n\tif (isErrorBody(body) && typeof body.message === 'string') {\n\t\tconst match = body.message.match(/Current plan: (\\w+)/);\n\t\tif (match?.[1]) return match[1];\n\t}\n\treturn 'unknown';\n}\n\nexport async function mapResponseToError(\n\tstatus: number,\n\theaders: { get(name: string): string | null },\n\tjsonFn: () => Promise<unknown>,\n): Promise<ScorioError> {\n\tlet body: unknown;\n\ttry {\n\t\tbody = await jsonFn();\n\t} catch {\n\t\tbody = null;\n\t}\n\n\tconst message = extractMessage(body);\n\n\tif (status === 403 && isErrorBody(body) && body.error === 'plan_limit') {\n\t\treturn new PlanLimitError(message, extractPlan(body));\n\t}\n\n\tif (status === 429) {\n\t\tconst retryAfter = Number(headers.get('retry-after') ?? '1');\n\t\treturn new RateLimitError(message, retryAfter);\n\t}\n\n\treturn new ScorioError(message, status, 'api_error');\n}\n\nexport { NetworkError };\n","import type {\n\tHttpClientPort,\n\tHttpRequest,\n\tHttpResponse,\n} from '../../application/ports/http-client.port.js';\nimport { NetworkError } from '../../domain/errors.js';\n\nexport class FetchHttpClient implements HttpClientPort {\n\tasync request(req: HttpRequest): Promise<HttpResponse> {\n\t\ttry {\n\t\t\tconst response = await fetch(req.url, {\n\t\t\t\tmethod: req.method,\n\t\t\t\theaders: req.headers,\n\t\t\t\tsignal: AbortSignal.timeout(req.timeout),\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tstatus: response.status,\n\t\t\t\theaders: response.headers,\n\t\t\t\tjson: () => response.json() as Promise<unknown>,\n\t\t\t};\n\t\t} catch (error: unknown) {\n\t\t\tif (error instanceof DOMException && error.name === 'TimeoutError') {\n\t\t\t\tthrow new NetworkError(`Request timed out after ${req.timeout}ms`);\n\t\t\t}\n\t\t\tif (error instanceof TypeError) {\n\t\t\t\tthrow new NetworkError('Network request failed', { cause: error });\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n","import type { DebugConfig, Plan } from '../../domain/types.js';\n\n/** Maps SDK plan names to the x-rapidapi-subscription header values\n * that the server's plan-guard.ts resolves to the correct internal tier. */\nconst PLAN_TO_HEADER: Record<Plan, string> = {\n\tfree: 'BASIC',\n\tstarter: 'STARTER',\n\tpro: 'ULTRA',\n\tbusiness: 'MEGA',\n};\n\nexport function buildHeaders(\n\tapiKey: string,\n\thost: string,\n\tdebug: DebugConfig | undefined,\n\tisSystem: boolean,\n): Record<string, string> {\n\tconst headers: Record<string, string> = {\n\t\tAccept: 'application/json',\n\t};\n\n\tif (isSystem) return headers;\n\n\tif (debug) {\n\t\theaders['x-rapidapi-proxy-secret'] = debug.secret;\n\t\tif (debug.plan) {\n\t\t\theaders['x-rapidapi-subscription'] = PLAN_TO_HEADER[debug.plan];\n\t\t}\n\t} else {\n\t\theaders['X-RapidAPI-Key'] = apiKey;\n\t\theaders['X-RapidAPI-Host'] = host;\n\t}\n\n\treturn headers;\n}\n","export function serializeParams(params?: Record<string, string | number | undefined>): string {\n\tif (!params) return '';\n\tconst entries: string[] = [];\n\tfor (const [k, v] of Object.entries(params)) {\n\t\tif (v !== undefined && v !== null && v !== '') {\n\t\t\tentries.push(`${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`);\n\t\t}\n\t}\n\treturn entries.join('&');\n}\n\nexport function buildUrl(\n\thost: string,\n\tpath: string,\n\tparams?: Record<string, string | number | undefined>,\n): string {\n\tconst base = `https://${host}${path}`;\n\tconst search = serializeParams(params);\n\treturn search ? `${base}?${search}` : base;\n}\n","import type {\n\tCompetition,\n\tGame,\n\tHealthResponse,\n\tListResponse,\n\tLiveSnapshot,\n\tOddsMover,\n\tOddsMoversOptions,\n\tOddsSummary,\n\tPaginationOptions,\n\tPingResponse,\n\tPriceHistoryOptions,\n\tPricePoint,\n\tRegion,\n\tScheduleOptions,\n\tScorioSDKConfig,\n\tSearchOptions,\n\tSingleResponse,\n\tSport,\n\tSportCount,\n\tStartingSoonOptions,\n} from '../domain/types.js';\nimport { mapResponseToError } from '../infrastructure/http/error-mapper.js';\nimport { FetchHttpClient } from '../infrastructure/http/fetch-client.js';\nimport { buildHeaders } from '../infrastructure/http/headers.js';\nimport { buildUrl } from '../infrastructure/http/url-builder.js';\nimport type { HttpClientPort } from './ports/http-client.port.js';\n\nexport default class ScorioSDK {\n\tprivate readonly apiKey: string;\n\tprivate readonly host: string;\n\tprivate readonly timeout: number;\n\tprivate readonly logger: boolean;\n\tprivate readonly config: ScorioSDKConfig;\n\tprivate readonly http: HttpClientPort;\n\n\tconstructor(config: ScorioSDKConfig, httpClient?: HttpClientPort) {\n\t\tif (!config.apiKey) {\n\t\t\tthrow new Error('apiKey is required');\n\t\t}\n\t\tthis.apiKey = config.apiKey;\n\t\tthis.host = config.debug?.host ?? config.host ?? '';\n\t\tthis.timeout = config.timeout ?? 30_000;\n\t\tthis.logger = config.logger ?? false;\n\t\tthis.config = config;\n\t\tthis.http = httpClient ?? new FetchHttpClient();\n\n\t\tif (!this.host) {\n\t\t\tthrow new Error('host is required (or provide debug.host)');\n\t\t}\n\t}\n\n\tprivate async get<T>(\n\t\tpath: string,\n\t\tparams?: Record<string, string | number | undefined>,\n\t\tisSystem = false,\n\t): Promise<T> {\n\t\tconst url = buildUrl(this.host, path, params);\n\t\tconst headers = buildHeaders(this.apiKey, this.host, this.config.debug, isSystem);\n\n\t\tif (this.logger) {\n\t\t\tconsole.log(`[scorio-sdk] GET ${path}`);\n\t\t}\n\n\t\tconst response = await this.http.request({\n\t\t\tmethod: 'GET',\n\t\t\turl,\n\t\t\theaders,\n\t\t\ttimeout: this.timeout,\n\t\t});\n\n\t\tif (response.status < 200 || response.status >= 300) {\n\t\t\tthrow await mapResponseToError(response.status, response.headers, response.json);\n\t\t}\n\n\t\treturn response.json() as Promise<T>;\n\t}\n\n\t// ─── Catalog ───────────────────────────────────────────────────\n\n\t/**\n\t * List all available sports.\n\t *\n\t * Returns every available sport sorted by display order.\n\t * Use this to build your top-level navigation or sport selector.\n\t *\n\t * @returns List of Sport objects with id, name, alias, and category.\n\t *\n\t * **Plans:** free, starter, pro, business | **Group:** catalog\n\t *\n\t * **Polling:** Cache locally for 60 seconds. The sport catalog changes infrequently.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data, meta } = await client.getSports();\n\t * // data: [{ id, name, alias, category }, ...]\n\t * // meta: { count: number }\n\t * ```\n\t */\n\tasync getSports(): Promise<ListResponse<Sport>> {\n\t\treturn this.get('/api/sports');\n\t}\n\n\t/**\n\t * Sports with live and prematch game counts.\n\t *\n\t * Returns all sports along with the number of currently live and upcoming prematch games for each.\n\t * Perfect for sidebar badges, sport selector counts, or deciding which sport feeds to subscribe to.\n\t *\n\t * @returns List of SportCount objects (Sport + live_count + prematch_count).\n\t *\n\t * **Plans:** free, starter, pro, business | **Group:** catalog\n\t *\n\t * **Polling:** Every 10-30 seconds. Counts change as games go live or finish.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data } = await client.getSportsCounts();\n\t * // data: [{ id, name, alias, category, live_count, prematch_count }, ...]\n\t * ```\n\t */\n\tasync getSportsCounts(): Promise<ListResponse<SportCount>> {\n\t\treturn this.get('/api/sports/counts');\n\t}\n\n\t/**\n\t * List regions for a sport.\n\t *\n\t * Returns all regions (countries or geographic areas) that currently have active games for the specified sport.\n\t * Build the second level of your navigation tree (e.g., England, Germany, Spain for Football).\n\t *\n\t * @param sportId - Unique sport identifier (ULID). Get IDs from {@link getSports}.\n\t * @returns List of Region objects with id, name, alias, and sport_id.\n\t *\n\t * **Plans:** free, starter, pro, business | **Group:** catalog\n\t *\n\t * **Polling:** Cache locally for 60 seconds.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data } = await client.getRegions('01KNSZTCFAHSBS092VMZS7PMCW');\n\t * // data: [{ id, name, alias, sport_id }, ...]\n\t * ```\n\t */\n\tasync getRegions(sportId: string): Promise<ListResponse<Region>> {\n\t\treturn this.get(`/api/sports/${sportId}/regions`);\n\t}\n\n\t/**\n\t * List competitions for a region.\n\t *\n\t * Returns all competitions (leagues, tournaments, cups) within the specified region.\n\t * Build the third level of your navigation tree (e.g., Premier League, Championship, FA Cup for England).\n\t *\n\t * @param regionId - Unique region identifier (ULID). Get IDs from {@link getRegions}.\n\t * @returns List of Competition objects with id, name, region_id, and sport_id.\n\t *\n\t * **Plans:** free, starter, pro, business | **Group:** catalog\n\t *\n\t * **Polling:** Cache locally for 60 seconds.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data } = await client.getCompetitions('01JRQ00000ENGLAND0000001');\n\t * // data: [{ id, name, region_id, sport_id }, ...]\n\t * ```\n\t */\n\tasync getCompetitions(regionId: string): Promise<ListResponse<Competition>> {\n\t\treturn this.get(`/api/regions/${regionId}/competitions`);\n\t}\n\n\t/**\n\t * List all competitions for a sport (flat list).\n\t *\n\t * Returns all competitions for the specified sport across ALL regions in one call.\n\t * Useful for building flat competition selectors, search/filter dropdowns, or schedule filters.\n\t *\n\t * @param sportId - Unique sport identifier (ULID). Get IDs from {@link getSports}.\n\t * @returns Flat list of Competition objects.\n\t *\n\t * **Plans:** free, starter, pro, business | **Group:** catalog\n\t *\n\t * **Polling:** Cache locally for 60 seconds.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data } = await client.getCompetitionsBySport('01KNSZTCFAHSBS092VMZS7PMCW');\n\t * // data: [{ id: \"...\", name: \"Premier League\", region_id, sport_id }, ...]\n\t * ```\n\t */\n\tasync getCompetitionsBySport(sportId: string): Promise<ListResponse<Competition>> {\n\t\treturn this.get(`/api/sports/${sportId}/competitions`);\n\t}\n\n\t// ─── Live ──────────────────────────────────────────────────────\n\n\t/**\n\t * All live games across all sports.\n\t *\n\t * Returns every currently live (in-play) game in a single call.\n\t * Ideal for multi-sport live tickers, aggregate live feeds, or monitoring total live game volume.\n\t *\n\t * @returns List of Game objects with is_live: true, including scores, stats, and market counts.\n\t *\n\t * **Plans:** starter, pro, business | **Group:** live\n\t *\n\t * **Polling:** Every 1-2 seconds for real-time updates.\n\t * At peak hours this can return 200+ games. If you only need one sport, use {@link getLiveGamesBySport}.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data } = await client.getAllLiveGames();\n\t * // data: [{ id, home_team, away_team, status: \"live\", score_text, info, stats, ... }, ...]\n\t * ```\n\t */\n\tasync getAllLiveGames(): Promise<ListResponse<Game>> {\n\t\treturn this.get('/api/live/games');\n\t}\n\n\t/**\n\t * Live games for a specific sport.\n\t *\n\t * Returns all currently live (in-play) games for the specified sport.\n\t * More efficient than {@link getAllLiveGames} when you only need one sport.\n\t *\n\t * @param sportId - Unique sport identifier (ULID). Get IDs from {@link getSports}.\n\t * @returns List of live Game objects filtered to the requested sport.\n\t *\n\t * **Plans:** starter, pro, business | **Group:** live\n\t *\n\t * **Polling:** Every 1-2 seconds for real-time updates.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data } = await client.getLiveGamesBySport('01KNSZTCFAHSBS092VMZS7PMCW');\n\t * // data: [{ id, home_team, away_team, score_text: \"2:1 (67')\", ... }, ...]\n\t * ```\n\t */\n\tasync getLiveGamesBySport(sportId: string): Promise<ListResponse<Game>> {\n\t\treturn this.get(`/api/live/games/${sportId}`);\n\t}\n\n\t/**\n\t * Full live dashboard snapshot.\n\t *\n\t * Returns a complete live dashboard in a single API call: sport counts and all live games combined.\n\t * Combines `/api/sports/counts` and `/api/live/games` to reduce round trips.\n\t *\n\t * @returns LiveSnapshot containing sports (with counts) and all live games.\n\t *\n\t * **Plans:** starter, pro, business | **Group:** live\n\t *\n\t * **Polling:** Every 2-5 seconds. This is a heavier endpoint.\n\t * For granular updates after initial load, prefer individual endpoints.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data } = await client.getLiveSnapshot();\n\t * // data: { sports: [{ id, name, live_count, prematch_count, ... }], games: [...] }\n\t * ```\n\t */\n\tasync getLiveSnapshot(): Promise<SingleResponse<LiveSnapshot>> {\n\t\treturn this.get('/api/live/snapshot');\n\t}\n\n\t// ─── Prematch ──────────────────────────────────────────────────\n\n\t/**\n\t * Prematch games for a sport (paginated).\n\t *\n\t * Returns upcoming (prematch) games for the specified sport with pagination support.\n\t * Sports like Football can have 1500+ prematch games.\n\t *\n\t * @param sportId - Unique sport identifier (ULID). Get IDs from {@link getSports}.\n\t * @param options - Pagination options: limit (1-100, default 50) and offset (default 0).\n\t * @returns Paginated list of prematch Game objects.\n\t *\n\t * **Plans:** starter, pro, business | **Group:** prematch\n\t *\n\t * **Polling:** Every 10-30 seconds. Prematch odds update less frequently than live.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data, meta } = await client.getPrematchGames('01KNSZTCFAHSBS092VMZS7PMCW', { limit: 20 });\n\t * // data: [{ id, home_team, away_team, status: \"prematch\", start_time, ... }, ...]\n\t * ```\n\t */\n\tasync getPrematchGames(\n\t\tsportId: string,\n\t\toptions?: PaginationOptions,\n\t): Promise<ListResponse<Game>> {\n\t\treturn this.get(`/api/prematch/games/${sportId}`, {\n\t\t\tlimit: options?.limit,\n\t\t\toffset: options?.offset,\n\t\t});\n\t}\n\n\t// ─── Games ─────────────────────────────────────────────────────\n\n\t/**\n\t * Games for a competition (paginated).\n\t *\n\t * Returns games for a specific competition with pagination.\n\t * Includes games that have recently started (up to 2 hours ago) and all upcoming games.\n\t *\n\t * @param competitionId - Unique competition identifier (ULID). Get IDs from {@link getCompetitions} or {@link getCompetitionsBySport}.\n\t * @param options - Pagination options: limit (1-100, default 50) and offset (default 0).\n\t * @returns Paginated list of Game objects sorted by start time.\n\t *\n\t * **Plans:** starter, pro, business | **Group:** games\n\t *\n\t * **Polling:** Every 10-30 seconds for prematch, 1-2 seconds if showing live games.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data } = await client.getGamesByCompetition('01KNSZTCFGMM6JE2B9YQFGQCDZ', { limit: 10 });\n\t * ```\n\t */\n\tasync getGamesByCompetition(\n\t\tcompetitionId: string,\n\t\toptions?: PaginationOptions,\n\t): Promise<ListResponse<Game>> {\n\t\treturn this.get(`/api/competitions/${competitionId}/games`, {\n\t\t\tlimit: options?.limit,\n\t\t\toffset: options?.offset,\n\t\t});\n\t}\n\n\t/**\n\t * Games starting within N minutes.\n\t *\n\t * Returns games that are about to start within the specified time window.\n\t * Great for \"Starting Soon\" widgets or last-minute bet notifications.\n\t *\n\t * @param options - minutes: time window (1-180, default 30).\n\t * @returns List of prematch Game objects sorted by start time (soonest first).\n\t *\n\t * **Plans:** starter, pro, business | **Group:** games\n\t *\n\t * **Polling:** Every 30-60 seconds.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data } = await client.getGamesStartingSoon({ minutes: 60 });\n\t * ```\n\t */\n\tasync getGamesStartingSoon(options?: StartingSoonOptions): Promise<ListResponse<Game>> {\n\t\treturn this.get('/api/games/starting-soon', {\n\t\t\tminutes: options?.minutes,\n\t\t});\n\t}\n\n\t/**\n\t * Search games by team name.\n\t *\n\t * Case-insensitive partial match against both home_team and away_team across all sports.\n\t * Sorted by relevance, then by start time.\n\t *\n\t * @param query - Search query string (minimum 2 characters).\n\t * @param options - limit: max results (1-50, default 20).\n\t * @returns List of matching Game objects.\n\t *\n\t * **Plans:** starter, pro, business | **Group:** games\n\t *\n\t * **Polling:** On demand (triggered by user input).\n\t *\n\t * @example\n\t * ```ts\n\t * const { data } = await client.searchGames('Arsenal', { limit: 10 });\n\t * ```\n\t */\n\tasync searchGames(query: string, options?: SearchOptions): Promise<ListResponse<Game>> {\n\t\treturn this.get('/api/games/search', {\n\t\t\tq: query,\n\t\t\tlimit: options?.limit,\n\t\t});\n\t}\n\n\t/**\n\t * Full game detail with all markets and odds.\n\t *\n\t * Returns complete data for a single game: metadata, all markets, and all outcomes.\n\t * Everything needed to render a full betting interface.\n\t *\n\t * @param gameId - Unique game identifier (ULID). Get IDs from any endpoint that returns Game objects.\n\t * @returns Single Game object with nested markets and outcomes.\n\t *\n\t * **Plans:** starter, pro, business | **Group:** games\n\t *\n\t * Markets are populated only on **pro** and **business** plans.\n\t * Lower plans receive `markets: []` and `markets_count: 0`.\n\t *\n\t * **Polling:** Every 1-2 seconds for live games, 10-30 seconds for prematch.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data } = await client.getGameDetail('01TESTGAME00000LIVESOC01');\n\t * // data.markets: [{ id, name, type, line, outcomes: [{ id, name, price, is_suspended }] }]\n\t * ```\n\t */\n\tasync getGameDetail(gameId: string): Promise<SingleResponse<Game>> {\n\t\treturn this.get(`/api/games/${gameId}`);\n\t}\n\n\t// ─── Schedule ──────────────────────────────────────────────────\n\n\t/**\n\t * Games by date or date range.\n\t *\n\t * Returns all games scheduled for a specific date or range, optionally filtered by sport or competition.\n\t * Uses UTC dates. Defaults to today if no date params provided.\n\t *\n\t * @param options - date (YYYY-MM-DD), dateFrom/dateTo (max 90 days), sportId, competitionId.\n\t * @returns List of Game objects sorted by start time.\n\t *\n\t * **Plans:** starter, pro, business | **Group:** schedule\n\t *\n\t * **Polling:** Every 60 seconds.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data } = await client.getSchedule({ date: '2026-04-10', sportId: '01KNSZTCFAHSBS092VMZS7PMCW' });\n\t * ```\n\t */\n\tasync getSchedule(options?: ScheduleOptions): Promise<ListResponse<Game>> {\n\t\treturn this.get('/api/schedule', {\n\t\t\tdate: options?.date,\n\t\t\tdate_from: options?.dateFrom,\n\t\t\tdate_to: options?.dateTo,\n\t\t\tsport_id: options?.sportId,\n\t\t\tcompetition_id: options?.competitionId,\n\t\t});\n\t}\n\n\t// ─── Odds Intelligence ─────────────────────────────────────────\n\n\t/**\n\t * Min/max/avg price summary per outcome for a game.\n\t *\n\t * Returns statistical summary of odds for every outcome: min, max, average price, and number of changes.\n\t * Useful for identifying value bets, overreactions, and market inefficiencies.\n\t *\n\t * @param gameId - Unique game identifier (ULID).\n\t * @returns List of OddsSummary objects, one per outcome.\n\t *\n\t * **Plans:** pro, business | **Group:** odds\n\t *\n\t * **Polling:** Every 10-30 seconds.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data } = await client.getGameOddsSummary('01TESTGAME00000LIVESOC01');\n\t * // data: [{ event_id, event_name, current_price, min_price, max_price, avg_price, change_count }]\n\t * ```\n\t */\n\tasync getGameOddsSummary(gameId: string): Promise<ListResponse<OddsSummary>> {\n\t\treturn this.get(`/api/games/${gameId}/odds-summary`);\n\t}\n\n\t/**\n\t * Top odds movements (biggest price changes).\n\t *\n\t * Returns outcomes with the largest odds movements within a given time window.\n\t * Key differentiator for professional bettors and odds aggregation platforms.\n\t *\n\t * @param options - minutes: look-back window (1-1440, default 60), limit: max results (1-100, default 20).\n\t * @returns List of OddsMover objects sorted by absolute change percentage (largest first).\n\t *\n\t * **Plans:** pro, business | **Group:** odds\n\t *\n\t * **Polling:** Every 5-10 seconds for near-real-time steam move alerts.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data } = await client.getOddsMovers({ minutes: 30, limit: 10 });\n\t * // data: [{ event_id, game_id, current_price, opening_price, price_change, change_percent, ... }]\n\t * ```\n\t */\n\tasync getOddsMovers(options?: OddsMoversOptions): Promise<ListResponse<OddsMover>> {\n\t\treturn this.get('/api/odds/movers', {\n\t\t\tminutes: options?.minutes,\n\t\t\tlimit: options?.limit,\n\t\t});\n\t}\n\n\t/**\n\t * Historical price changes for an outcome.\n\t *\n\t * Returns the full history of price changes for a specific outcome (selection).\n\t * Build odds movement charts, sparklines, or trend analysis visualizations.\n\t * 60-day retention, tick-level granularity.\n\t *\n\t * @param eventId - Unique outcome identifier (ULID). Get IDs from Game objects with markets.\n\t * @param options - from/to (unix timestamps), limit (1-5000, default 500).\n\t * @returns Chronological list of PricePoint objects (oldest first).\n\t *\n\t * **Plans:** pro, business | **Group:** odds\n\t *\n\t * **Polling:** On demand.\n\t *\n\t * @example\n\t * ```ts\n\t * const { data } = await client.getEventPriceHistory('01TESTEVT00000ARS0NAL01', { limit: 100 });\n\t * // data: [{ price, previous_price, recorded_at }, ...]\n\t * ```\n\t */\n\tasync getEventPriceHistory(\n\t\teventId: string,\n\t\toptions?: PriceHistoryOptions,\n\t): Promise<ListResponse<PricePoint>> {\n\t\treturn this.get(`/api/events/${eventId}/price-history`, {\n\t\t\tfrom: options?.from,\n\t\t\tto: options?.to,\n\t\t\tlimit: options?.limit,\n\t\t});\n\t}\n\n\t// ─── System ────────────────────────────────────────────────────\n\n\t/**\n\t * Health check.\n\t *\n\t * Returns the current health status of the API. No authentication required.\n\t * Use in load balancer health checks, uptime monitoring, or status pages.\n\t *\n\t * @returns `{ status: \"ok\" }` when the API is healthy.\n\t *\n\t * **Plans:** all (no authentication required) | **Group:** system\n\t *\n\t * **Polling:** Every 30-60 seconds from your monitoring system.\n\t */\n\tasync health(): Promise<HealthResponse> {\n\t\treturn this.get('/api/health', undefined, true);\n\t}\n\n\t/**\n\t * Ping.\n\t *\n\t * Simple connectivity check. No authentication required.\n\t * Quick liveness probe for monitoring or client-side connectivity checks.\n\t *\n\t * @returns `{ pong: true }`\n\t *\n\t * **Plans:** all (no authentication required) | **Group:** system\n\t */\n\tasync ping(): Promise<PingResponse> {\n\t\treturn this.get('/api/ping', undefined, true);\n\t}\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@scorio/client-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "TypeScript SDK for the Scorio Sports API — real-time odds, live scores, and historical price analytics across 80+ sports",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"keywords": [
|
|
20
|
+
"sports",
|
|
21
|
+
"betting",
|
|
22
|
+
"odds",
|
|
23
|
+
"live-scores",
|
|
24
|
+
"sports-data",
|
|
25
|
+
"sportsbook",
|
|
26
|
+
"sports-api",
|
|
27
|
+
"odds-api",
|
|
28
|
+
"betting-api",
|
|
29
|
+
"live-betting",
|
|
30
|
+
"prematch",
|
|
31
|
+
"price-history",
|
|
32
|
+
"football",
|
|
33
|
+
"basketball",
|
|
34
|
+
"tennis",
|
|
35
|
+
"esports",
|
|
36
|
+
"rapidapi",
|
|
37
|
+
"sdk",
|
|
38
|
+
"typescript"
|
|
39
|
+
],
|
|
40
|
+
"author": "Scorio <support@sportsdataapi.com>",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"homepage": "https://github.com/ts-ign0re/scorio#readme",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "https://github.com/ts-ign0re/scorio.git",
|
|
46
|
+
"directory": "packages/scorio-sdk"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsup",
|
|
50
|
+
"check": "tsc --noEmit",
|
|
51
|
+
"test": "vitest run",
|
|
52
|
+
"test:watch": "vitest",
|
|
53
|
+
"test:integration": "vitest run src/__tests__/integration/",
|
|
54
|
+
"test:build": "tsup && vitest run -c vitest.build.config.ts src/__tests__/integration/",
|
|
55
|
+
"clean": "rm -rf dist *.tsbuildinfo"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"tsup": "^8.4.0",
|
|
59
|
+
"vitest": "^4.1.4"
|
|
60
|
+
}
|
|
61
|
+
}
|