Patch 6.2.0 is live — Clean up of duplicated endpoints & improvement of Typescript SDK.
api-fortnite
← Back to Blog

How to Build a Fortnite Discord Bot with the API

Step-by-step guide to building a Fortnite Discord bot that posts daily item shop updates and looks up player stats using the real Fortnite API endpoints.

discord-bottutorialjavascript

Why Build a Fortnite Discord Bot?


Discord bots are one of the most popular use cases for the Fortnite API. They let your gaming community check player stats, see the daily item shop, and get notified about updates — all without leaving Discord.


Prerequisites


  • Node.js 18+
  • A Discord application and bot token (from the Discord Developer Portal)
  • A Fortnite API key from api-fortnite.com

  • Setup


    npm install discord.js node-cron dotenv

    Create a .env file:


    DISCORD_TOKEN=your_discord_bot_token
    FORTNITE_API_KEY=your_api_key
    SHOP_CHANNEL_ID=your_channel_id

    Key Concept: Stats Use Account IDs


    The stats endpoint requires an Epic account ID, not a display name. You always resolve the display name first:


    GET /api/v1/account/displayName/{displayName}
    → returns { id: "...", displayName: "..." }
    
    GET /api/v2/stats/{accountId}
    → returns player stats

    Slash Command: /stats


    const { SlashCommandBuilder } = require("discord.js");
    
    const BASE_URL = "https://prod.api-fortnite.com";
    const HEADERS = { "x-api-key": process.env.FORTNITE_API_KEY };
    
    module.exports = {
      data: new SlashCommandBuilder()
        .setName("stats")
        .setDescription("Look up Fortnite player stats")
        .addStringOption((opt) =>
          opt.setName("username").setDescription("Epic Games display name").setRequired(true)
        ),
    
      async execute(interaction) {
        const displayName = interaction.options.getString("username");
        await interaction.deferReply();
    
        try {
          // Step 1: resolve display name → account ID
          const accountRes = await fetch(
            `${BASE_URL}/api/v1/account/displayName/${encodeURIComponent(displayName)}`,
            { headers: HEADERS }
          );
          if (!accountRes.ok) {
            return interaction.editReply(`Player **${displayName}** not found.`);
          }
          const account = await accountRes.json();
    
          // Step 2: fetch stats
          const statsRes = await fetch(
            `${BASE_URL}/api/v2/stats/${account.id}`,
            { headers: HEADERS }
          );
          const stats = await statsRes.json();
    
          await interaction.editReply(
            `**${displayName}** — stats loaded!`
            // Adapt to the actual fields in the stats response
          );
        } catch (err) {
          await interaction.editReply("Could not retrieve stats. The player may have private stats.");
        }
      },
    };

    Daily Item Shop Notification


    Post the shop automatically every day at reset (00:05 UTC):


    const cron = require("node-cron");
    
    cron.schedule("5 0 * * *", async () => {
      const res = await fetch("https://prod.api-fortnite.com/api/v1/shop", {
        headers: { "x-api-key": process.env.FORTNITE_API_KEY },
      });
      const shop = await res.json();
    
      const channel = await client.channels.fetch(process.env.SHOP_CHANNEL_ID);
      await channel.send("**The item shop has reset!** Check today's rotation.");
    });

    Other Useful Endpoints for Bots


    | Command idea | Endpoint |

    |---|---|

    | /news — latest BR news | GET /api/v1/news/br |

    | /map — current map info | GET /api/v1/map |

    | /season — current season | GET /api/v1/season |

    | /cosmetic — search a skin | GET /api/v2/cosmetics/search?q=Raven |

    | /weapons — weapon stats | GET /api/v2/weapons |


    Tips


  • Cache the shop — It only changes once daily. Store the response and reuse it until midnight UTC.
  • Privacy settings — Some players hide their stats. Always handle the case where the stats endpoint returns no data.
  • Rate limits — The free tier has per-minute and daily limits. Use caching to stay within them.

  • Related Guides


  • Getting Started with the Fortnite API
  • Fortnite Item Shop API - Complete Guide