@yaelouuu/fortnite-api 4.5.0 → 5.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.
@@ -1,5 +1,5 @@
1
1
  import { FortniteAPI } from "../client";
2
- import { EventWindows, PlayerEventHistory, TournamentDetails, ScoringRules, EventLeaderboard, PlayerEventData, EligibilityStatus, ArenaHype, EventRewards } from "../types";
2
+ import { EventWindows, PlayerEventHistory, TournamentDetails, ScoringRules, EventLeaderboard, PlayerEventData, EligibilityStatus, PlayerEligibilityResult, ArenaHype, EventRewards } from "../types";
3
3
  /**
4
4
  * Events Resource
5
5
  * Handles tournament and competitive events data
@@ -58,13 +58,25 @@ export declare class EventsResource {
58
58
  */
59
59
  getPlayerEventData(eventId: string, eventWindowId: string, accountId: string, fortniteToken?: string): Promise<PlayerEventData>;
60
60
  /**
61
- * Check tournament eligibility
62
- * @param accountId - Account ID
63
- * @param eventId - Event ID
64
- * @param fortniteToken - User Fortnite token (REQUIRED)
65
- * @returns Eligibility status
61
+ * Get parsed tournament eligibility requirements.
62
+ * No user token needed — requirements are extracted from tournament metadata.
63
+ * @param eventId - Event ID (e.g. epicgames_S39_RankedCupDuosBR_ASIA)
64
+ * @param eventWindowId - Optional: filter to a specific event window
65
+ * @returns Parsed eligibility requirements
66
+ */
67
+ checkEligibility(eventId: string, eventWindowId?: string): Promise<EligibilityStatus>;
68
+ /**
69
+ * Check a player's eligibility against tournament requirements.
70
+ * Cross-references ranked data with tournament requirements — no user token needed.
71
+ * @param eventId - Event ID (e.g. epicgames_S39_RankedCupDuosBR_ASIA)
72
+ * @param accountId - Epic Games Account ID to check
73
+ * @param options - Optional platform and eventWindowId
74
+ * @returns Player eligibility check results
66
75
  */
67
- checkEligibility(accountId: string, eventId: string, fortniteToken: string): Promise<EligibilityStatus>;
76
+ checkPlayerEligibility(eventId: string, accountId: string, options?: {
77
+ platform?: string;
78
+ eventWindowId?: string;
79
+ }): Promise<PlayerEligibilityResult>;
68
80
  /**
69
81
  * Get Arena hype and division
70
82
  * @param accountId - Account ID
@@ -95,17 +95,32 @@ class EventsResource {
95
95
  return this.client.request(`/events/${eventId}/windows/${eventWindowId}/players/${accountId}`, { headers }, "v2");
96
96
  }
97
97
  /**
98
- * Check tournament eligibility
99
- * @param accountId - Account ID
100
- * @param eventId - Event ID
101
- * @param fortniteToken - User Fortnite token (REQUIRED)
102
- * @returns Eligibility status
98
+ * Get parsed tournament eligibility requirements.
99
+ * No user token needed — requirements are extracted from tournament metadata.
100
+ * @param eventId - Event ID (e.g. epicgames_S39_RankedCupDuosBR_ASIA)
101
+ * @param eventWindowId - Optional: filter to a specific event window
102
+ * @returns Parsed eligibility requirements
103
+ */
104
+ async checkEligibility(eventId, eventWindowId) {
105
+ const query = eventWindowId ? `?eventWindowId=${eventWindowId}` : "";
106
+ return this.client.request(`/events/${eventId}/eligibility${query}`, {}, "v2");
107
+ }
108
+ /**
109
+ * Check a player's eligibility against tournament requirements.
110
+ * Cross-references ranked data with tournament requirements — no user token needed.
111
+ * @param eventId - Event ID (e.g. epicgames_S39_RankedCupDuosBR_ASIA)
112
+ * @param accountId - Epic Games Account ID to check
113
+ * @param options - Optional platform and eventWindowId
114
+ * @returns Player eligibility check results
103
115
  */
104
- async checkEligibility(accountId, eventId, fortniteToken) {
105
- const headers = {
106
- "x-fortnite-token": fortniteToken,
107
- };
108
- return this.client.request(`/events/${eventId}/eligibility/${accountId}`, { headers }, "v2");
116
+ async checkPlayerEligibility(eventId, accountId, options) {
117
+ const params = new URLSearchParams();
118
+ if (options?.platform)
119
+ params.set("platform", options.platform);
120
+ if (options?.eventWindowId)
121
+ params.set("eventWindowId", options.eventWindowId);
122
+ const query = params.toString() ? `?${params.toString()}` : "";
123
+ return this.client.request(`/events/${eventId}/eligibility/${accountId}${query}`, {}, "v2");
109
124
  }
110
125
  /**
111
126
  * Get Arena hype and division
@@ -1,5 +1,5 @@
1
1
  import { FortniteAPI } from "../client";
2
- import { OAuthCompleteResponse, OAuthDeviceRefreshResponse, OAuthFlowResponse, OAuthRefreshResponse } from "../types";
2
+ import { OAuthCompleteResponse, OAuthDeviceRefreshResponse, OAuthExchangeCodeResponse, OAuthFlowResponse, OAuthRefreshResponse } from "../types";
3
3
  export declare class OauthResource {
4
4
  private client;
5
5
  constructor(client: FortniteAPI);
@@ -18,6 +18,16 @@ export declare class OauthResource {
18
18
  * Use when access token expires (~2 hours)
19
19
  */
20
20
  refreshToken(refreshToken: string): Promise<OAuthRefreshResponse>;
21
+ /**
22
+ * Exchange authorization code for tokens - POST /oauth/exchange-code
23
+ * Clean web OAuth flow (no device code warning)
24
+ */
25
+ exchangeCode(params: {
26
+ code: string;
27
+ redirectUri: string;
28
+ clientId?: string;
29
+ clientSecret?: string;
30
+ }): Promise<OAuthExchangeCodeResponse>;
21
31
  /**
22
32
  * Refresh with device auth - POST /oauth/refresh-device
23
33
  * Use device auth credentials to get fresh tokens (never expires)
@@ -32,6 +32,16 @@ class OauthResource {
32
32
  body: JSON.stringify({ refreshToken }),
33
33
  });
34
34
  }
35
+ /**
36
+ * Exchange authorization code for tokens - POST /oauth/exchange-code
37
+ * Clean web OAuth flow (no device code warning)
38
+ */
39
+ async exchangeCode(params) {
40
+ return this.client.request("/oauth/exchange-code", {
41
+ method: "POST",
42
+ body: JSON.stringify(params),
43
+ });
44
+ }
35
45
  /**
36
46
  * Refresh with device auth - POST /oauth/refresh-device
37
47
  * Use device auth credentials to get fresh tokens (never expires)
@@ -4,19 +4,24 @@ export declare class ProfilesResource {
4
4
  private client;
5
5
  constructor(client: FortniteAPI);
6
6
  /**
7
- * Get profile progress by display name
7
+ * Get profile progress (ranked divisions, levels) by display name
8
+ * @param displayName - Epic Games display name
8
9
  */
9
10
  getProgress(displayName: string): Promise<any>;
10
11
  /**
11
12
  * Get profile stats by display name
13
+ * @param displayName - Epic Games display name
14
+ * @param timeWindow - Time period: "season" or "lifetime" (default: "lifetime")
12
15
  */
13
- getStats(displayName: string): Promise<ProfileStats>;
16
+ getStats(displayName: string, timeWindow?: "season" | "lifetime"): Promise<ProfileStats>;
14
17
  /**
15
18
  * Get account info by ID
19
+ * @param accountId - Epic Games Account ID
16
20
  */
17
21
  getAccount(accountId: string): Promise<Profile>;
18
22
  /**
19
- * Get multiple display names
23
+ * Get multiple display names by account IDs
24
+ * @param accountIds - Array of account IDs (max 100)
20
25
  */
21
26
  getDisplayNames(accountIds: string[]): Promise<Record<string, string>>;
22
27
  }
@@ -6,29 +6,39 @@ class ProfilesResource {
6
6
  this.client = client;
7
7
  }
8
8
  /**
9
- * Get profile progress by display name
9
+ * Get profile progress (ranked divisions, levels) by display name
10
+ * @param displayName - Epic Games display name
10
11
  */
11
12
  async getProgress(displayName) {
12
- return this.client.request(`/profile/progress?displayName=${displayName}`);
13
+ return this.client.request(`/profile/progress?displayName=${encodeURIComponent(displayName)}`);
13
14
  }
14
15
  /**
15
16
  * Get profile stats by display name
17
+ * @param displayName - Epic Games display name
18
+ * @param timeWindow - Time period: "season" or "lifetime" (default: "lifetime")
16
19
  */
17
- async getStats(displayName) {
18
- return this.client.request(`/profile/stats?displayName=${displayName}`);
20
+ async getStats(displayName, timeWindow) {
21
+ const params = new URLSearchParams({
22
+ displayName,
23
+ });
24
+ if (timeWindow)
25
+ params.set("timeWindow", timeWindow);
26
+ return this.client.request(`/profile/stats?${params.toString()}`);
19
27
  }
20
28
  /**
21
29
  * Get account info by ID
30
+ * @param accountId - Epic Games Account ID
22
31
  */
23
32
  async getAccount(accountId) {
24
33
  return this.client.request(`/account/${accountId}`);
25
34
  }
26
35
  /**
27
- * Get multiple display names
36
+ * Get multiple display names by account IDs
37
+ * @param accountIds - Array of account IDs (max 100)
28
38
  */
29
39
  async getDisplayNames(accountIds) {
30
40
  const ids = accountIds.join(",");
31
- return this.client.request(`/displaynames/multiple?ids=${ids}`);
41
+ return this.client.request(`/displaynames/multiple?ids=${encodeURIComponent(ids)}`);
32
42
  }
33
43
  }
34
44
  exports.ProfilesResource = ProfilesResource;
@@ -4,7 +4,17 @@ export declare class ShopResource {
4
4
  private client;
5
5
  constructor(client: FortniteAPI);
6
6
  /**
7
- * Get current shop items
7
+ * Get current shop items with optional filtering
8
+ * @param options - Query options
9
+ * @param options.type - Filter by cosmetic type: outfit, emote, pickaxe, glider, backpack, wrap, music, loadingscreen, contrail, spray, toy, emoji, pet, bundle
10
+ * @param options.section - Filter by shop section name (e.g. "Featured", "Daily", "Kicks")
11
+ * @param options.rarity - Filter by rarity: common, uncommon, rare, epic, legendary, mythic
12
+ * @param options.search - Search items by name (e.g. "galaxy", "travis")
8
13
  */
9
- getCurrent(): Promise<Shop>;
14
+ getCurrent(options?: {
15
+ type?: string;
16
+ section?: string;
17
+ rarity?: string;
18
+ search?: string;
19
+ }): Promise<Shop>;
10
20
  }
@@ -6,10 +6,25 @@ class ShopResource {
6
6
  this.client = client;
7
7
  }
8
8
  /**
9
- * Get current shop items
9
+ * Get current shop items with optional filtering
10
+ * @param options - Query options
11
+ * @param options.type - Filter by cosmetic type: outfit, emote, pickaxe, glider, backpack, wrap, music, loadingscreen, contrail, spray, toy, emoji, pet, bundle
12
+ * @param options.section - Filter by shop section name (e.g. "Featured", "Daily", "Kicks")
13
+ * @param options.rarity - Filter by rarity: common, uncommon, rare, epic, legendary, mythic
14
+ * @param options.search - Search items by name (e.g. "galaxy", "travis")
10
15
  */
11
- async getCurrent() {
12
- return this.client.request("/shop");
16
+ async getCurrent(options) {
17
+ const params = new URLSearchParams();
18
+ if (options?.type)
19
+ params.set("type", options.type);
20
+ if (options?.section)
21
+ params.set("section", options.section);
22
+ if (options?.rarity)
23
+ params.set("rarity", options.rarity);
24
+ if (options?.search)
25
+ params.set("search", options.search);
26
+ const query = params.toString() ? `?${params.toString()}` : "";
27
+ return this.client.request(`/shop${query}`);
13
28
  }
14
29
  }
15
30
  exports.ShopResource = ShopResource;
@@ -1,10 +1,29 @@
1
1
  import { FortniteAPI } from "../client";
2
- import { Weapons } from "../types";
2
+ import { WeaponsResponse } from "../types";
3
3
  export declare class WeaponsResource {
4
4
  private client;
5
5
  constructor(client: FortniteAPI);
6
6
  /**
7
- * Get weapons and infos
7
+ * Get weapons data with optional filtering
8
+ * @param options - Query options
9
+ * @param options.version - Version filter: "current" (loot pool), "all" (every weapon), or a specific patch like "39.50"
10
+ * @param options.category - Filter by category: assault-rifle, shotgun, smg, sniper, pistol, explosive, bow, crossbow, melee, light-machine-gun
11
+ * @param options.search - Search weapons by name (e.g. "pump", "assault", "bolt")
12
+ * @param options.gamemode - Filter by gamemode: "br" (Battle Royale) or "og" (OG mode)
13
+ * @param options.rarity - Filter by rarity: common, uncommon, rare, epic, legendary, mythic, transcendent
14
+ * @param options.type - Filter by weapon type: ranged, melee, consumable, trap, gadget
15
+ * @param options.ammoType - Filter by ammo type: light, medium, heavy, shells, rockets, energy, arrows
16
+ * @param options.season - Filter by season availability: "CH6S7" or "6.7" format
17
+ * @returns Weapons response with metadata, availableSeasons, and weapon data
8
18
  */
9
- getWeapons(): Promise<Weapons>;
19
+ getWeapons(options?: {
20
+ version?: string;
21
+ category?: string;
22
+ search?: string;
23
+ gamemode?: "br" | "og";
24
+ rarity?: string;
25
+ type?: string;
26
+ ammoType?: string;
27
+ season?: string;
28
+ }): Promise<WeaponsResponse>;
10
29
  }
@@ -6,10 +6,38 @@ class WeaponsResource {
6
6
  this.client = client;
7
7
  }
8
8
  /**
9
- * Get weapons and infos
9
+ * Get weapons data with optional filtering
10
+ * @param options - Query options
11
+ * @param options.version - Version filter: "current" (loot pool), "all" (every weapon), or a specific patch like "39.50"
12
+ * @param options.category - Filter by category: assault-rifle, shotgun, smg, sniper, pistol, explosive, bow, crossbow, melee, light-machine-gun
13
+ * @param options.search - Search weapons by name (e.g. "pump", "assault", "bolt")
14
+ * @param options.gamemode - Filter by gamemode: "br" (Battle Royale) or "og" (OG mode)
15
+ * @param options.rarity - Filter by rarity: common, uncommon, rare, epic, legendary, mythic, transcendent
16
+ * @param options.type - Filter by weapon type: ranged, melee, consumable, trap, gadget
17
+ * @param options.ammoType - Filter by ammo type: light, medium, heavy, shells, rockets, energy, arrows
18
+ * @param options.season - Filter by season availability: "CH6S7" or "6.7" format
19
+ * @returns Weapons response with metadata, availableSeasons, and weapon data
10
20
  */
11
- async getWeapons() {
12
- return this.client.request("/weapons", {}, "v2");
21
+ async getWeapons(options) {
22
+ const params = new URLSearchParams();
23
+ if (options?.version)
24
+ params.set("version", options.version);
25
+ if (options?.category)
26
+ params.set("category", options.category);
27
+ if (options?.search)
28
+ params.set("search", options.search);
29
+ if (options?.gamemode)
30
+ params.set("gamemode", options.gamemode);
31
+ if (options?.rarity)
32
+ params.set("rarity", options.rarity);
33
+ if (options?.type)
34
+ params.set("type", options.type);
35
+ if (options?.ammoType)
36
+ params.set("ammoType", options.ammoType);
37
+ if (options?.season)
38
+ params.set("season", options.season);
39
+ const query = params.toString() ? `?${params.toString()}` : "";
40
+ return this.client.request(`/weapons${query}`, {}, "v2");
13
41
  }
14
42
  }
15
43
  exports.WeaponsResource = WeaponsResource;
@@ -12,7 +12,7 @@ export interface CatalogEntry {
12
12
  offerId: string;
13
13
  devName: string;
14
14
  offerType: string;
15
- prices: Price[];
15
+ prices: ShopPrice[];
16
16
  categories: string[];
17
17
  dailyLimit: number;
18
18
  weeklyLimit: number;
@@ -28,18 +28,57 @@ export interface CatalogEntry {
28
28
  shortDescription: string;
29
29
  description: string;
30
30
  displayAssetPath: string;
31
- itemGrants: ItemGrant[];
31
+ itemGrants: EnrichedItemGrant[];
32
32
  giftInfo?: GiftInfo;
33
+ bundle: ShopBundle | null;
34
+ sectionId: string | null;
35
+ sectionDisplayName: string;
36
+ sectionPriority: number;
37
+ sectionBackground: string | null;
38
+ offerVisual: string | null;
39
+ tileSize: string | null;
33
40
  }
34
- export interface Price {
41
+ export interface ShopPrice {
35
42
  currencyType: string;
36
- currencySubType: string;
37
43
  regularPrice: number;
38
- dynamicRegularPrice: number;
39
44
  finalPrice: number;
40
- saleExpiration: string;
41
- basePrice: number;
42
- saleType?: string;
45
+ saleType: string | null;
46
+ }
47
+ export interface ShopBundle {
48
+ name: string | null;
49
+ info: string;
50
+ items: number;
51
+ regularPrice: number;
52
+ finalPrice: number;
53
+ discount: number | null;
54
+ }
55
+ export interface EnrichedItemGrant {
56
+ templateId: string;
57
+ quantity: number;
58
+ attributes: Record<string, any>;
59
+ cosmetic: CosmeticEnrichment | null;
60
+ }
61
+ export interface CosmeticEnrichment {
62
+ type: string;
63
+ name: string;
64
+ displayName: string;
65
+ description: string;
66
+ shortDescription: string;
67
+ rarity: string;
68
+ images: {
69
+ icon: string | null;
70
+ largeIcon: string | null;
71
+ };
72
+ gender: string | null;
73
+ tags: string[];
74
+ set: {
75
+ value: string;
76
+ backendValue: string;
77
+ } | null;
78
+ introduction: {
79
+ chapter: number | null;
80
+ season: number | null;
81
+ };
43
82
  }
44
83
  export interface Requirement {
45
84
  requirementType: string;
@@ -50,11 +89,6 @@ export interface MetaInfo {
50
89
  key: string;
51
90
  value: string;
52
91
  }
53
- export interface ItemGrant {
54
- templateId: string;
55
- quantity: number;
56
- attributes: Record<string, any>;
57
- }
58
92
  export interface GiftInfo {
59
93
  bIsEnabled: boolean;
60
94
  forcedGiftBoxTemplateId: string;
@@ -180,24 +214,52 @@ export interface TournamentEligibilityResponse {
180
214
  newest_tournament_date: string | null;
181
215
  recent_tournaments: TournamentTrackerEntry[];
182
216
  }
183
- export interface Weapons {
184
- key: WeaponsInfos;
217
+ export interface SeasonEntry {
218
+ chapter: number;
219
+ season: number;
220
+ patch: string;
221
+ }
222
+ export interface WeaponsResponse {
223
+ version: string;
224
+ count: number;
225
+ source: "cue4parse" | "lootpool" | "map-archives";
226
+ availableSeasons: SeasonEntry[];
227
+ lootPool?: {
228
+ patchVersion: string;
229
+ lastUpdated: string;
230
+ replaysProcessed: number;
231
+ };
232
+ data: Record<string, WeaponsInfos>;
185
233
  }
234
+ /** @deprecated Use WeaponsResponse instead */
235
+ export type Weapons = WeaponsResponse;
186
236
  export interface WeaponsInfos {
187
237
  id: string;
188
238
  displayName: string;
189
239
  description: string;
190
240
  rarity: string;
191
- gameplayTags: GameplayTags;
192
- icon: string;
193
241
  type: string;
194
242
  category: string | null;
195
- season: number;
196
- series: string;
243
+ season: {
244
+ chapter: number;
245
+ season: number;
246
+ } | null;
247
+ introductionSeason: {
248
+ chapter: number;
249
+ season: number;
250
+ } | null;
251
+ seasons: SeasonEntry[];
252
+ gamemode: "br" | "og";
253
+ ammoType: string | null;
254
+ triggerType: string | null;
255
+ tags: string[];
256
+ searchTags: string;
197
257
  stats: WeaponsStats;
198
- }
199
- export interface GameplayTags {
200
- gameplayTags: Array<String>;
258
+ images: {
259
+ icon: string | null;
260
+ iconNoBackground: string | null;
261
+ largeIcon: string | null;
262
+ };
201
263
  }
202
264
  export interface WeaponsStats {
203
265
  firingRate: number;
@@ -479,9 +541,98 @@ export interface PlayerEventData {
479
541
  percentile?: number;
480
542
  sessions?: Array<any>;
481
543
  }
544
+ export interface RankRequirement {
545
+ raw: string;
546
+ trackId?: string;
547
+ minimumRank?: number;
548
+ }
549
+ export interface WindowRequirements {
550
+ mfa: boolean;
551
+ eula: string | null;
552
+ anticheat: string | null;
553
+ rankRequirements: RankRequirement[] | null;
554
+ }
555
+ export interface EligibilityWindow {
556
+ eventWindowId: string;
557
+ beginTime: string;
558
+ endTime: string;
559
+ round: number;
560
+ requireAllTokens: string[];
561
+ requireAnyTokens: string[];
562
+ requireNoneTokensCaller: string[];
563
+ teammateEligibility: string | null;
564
+ requirements: WindowRequirements;
565
+ }
566
+ export interface EligibilityRequirements {
567
+ minimumAccountLevel: number | null;
568
+ platforms: string[];
569
+ systemFeatures: string[];
570
+ tournamentType: string | null;
571
+ regionLockType: string | null;
572
+ accountLockType: string | null;
573
+ teamLockType: string | null;
574
+ disqualifyType: string | null;
575
+ }
482
576
  export interface EligibilityStatus {
483
- eligible: boolean;
484
- reasons?: string[];
577
+ eventId: string;
578
+ region: string;
579
+ groupId: string;
580
+ name: string;
581
+ requirements: EligibilityRequirements;
582
+ windows: EligibilityWindow[];
583
+ }
584
+ export interface EligibilityCheck {
585
+ status: "pass" | "fail" | "unknown";
586
+ required?: any;
587
+ message?: string;
588
+ playerPlatform?: string;
589
+ }
590
+ export interface RankCheck {
591
+ status: "pass" | "fail" | "unknown";
592
+ type: "OR";
593
+ details: Array<{
594
+ trackId: string;
595
+ minimumRank: number;
596
+ playerDivision: number | null;
597
+ status: "pass" | "fail" | "unknown";
598
+ }>;
599
+ }
600
+ export interface PlayerEligibilityWindow {
601
+ eventWindowId: string;
602
+ checks: {
603
+ mfa?: EligibilityCheck;
604
+ eula?: EligibilityCheck;
605
+ rank?: RankCheck;
606
+ requireNoneTokensCaller?: EligibilityCheck;
607
+ };
608
+ }
609
+ export interface PlayerEligibilityResult {
610
+ eventId: string;
611
+ accountId: string;
612
+ region: string;
613
+ name: string;
614
+ checks: {
615
+ minimumAccountLevel?: EligibilityCheck;
616
+ platform?: EligibilityCheck;
617
+ systemFeatures?: EligibilityCheck;
618
+ };
619
+ windows: PlayerEligibilityWindow[];
620
+ playerRanks: Record<string, {
621
+ currentDivision: number | null;
622
+ highestDivision: number | null;
623
+ currentPlayerRanking: number | null;
624
+ }>;
625
+ checkedAt: string;
626
+ }
627
+ export interface OAuthExchangeCodeResponse {
628
+ success: boolean;
629
+ accessToken: string;
630
+ refreshToken: string;
631
+ expiresIn: number;
632
+ tokenType: string;
633
+ scope: string;
634
+ accountId: string;
635
+ displayName: string | null;
485
636
  }
486
637
  export interface ArenaHype {
487
638
  accountId: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaelouuu/fortnite-api",
3
- "version": "4.5.0",
3
+ "version": "5.0.0",
4
4
  "description": "SDK for Fortnite Tournaments API by Royal Arena - Author : Yael Brinkert",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",