---
title: "SDK Events"
description: "Ready, chat, friends, party, and cosmetic events from local shards."
canonical: "https://developers.fnlb.net/docs/sdk/events"
markdown: "/docs/sdk/events.md"
---

> ## Documentation Index
> Fetch the complete documentation index at: https://developers.fnlb.net/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK Events

---
title: "SDK events"
sidebarTitle: "Events"
description: "Listen for ready, chat, friends, party, and cosmetic events from the local shards."
icon: "gateway"
---

`fnlb` is an event emitter. Import `Events` from `fnlb` and pass the enum to `fnlb.on` or `fnlb.once`. Names are stable strings such as `ready` and `party:member:message`.

Party and friend chat arrive as a `Message`. `ready` arrives as a `Bot`. Other events arrive as `{ bot, ...fields }`. Full party meta is not on the event. Call `bot.party.meta.get()` when you need the schema. See [Bots and parties](/docs/sdk/parties.md).

```ts
import FNLB, { Events } from 'fnlb';

const fnlb = new FNLB();

fnlb.on(Events.Ready, (bot) => {
  console.log(bot.id, bot.displayName);
});

fnlb.on(Events.PartyMemberMessage, async (message) => {
  if (message.content === '!ping') await message.reply('pong');
});
```

<Info>
Register listeners before `start()`. A bot can emit `ready` as soon as its shard finishes logging in.
</Info>

## Lifecycle

| Event | Payload | When |
| :--- | :--- | :--- |
| `Events.Ready` | `Bot` | The Fortnite client finished logging this bot in. |
| `Events.Disconnected` | `{ bot, isLogout }` | The Fortnite client disconnected. |
| `Events.ShardReady` | `Shard` | A shard process opened the local SDK bridge and can take IPC calls. |

## Chat

| Event | Payload | When |
| :--- | :--- | :--- |
| `Events.PartyMemberMessage` | `Message` with `channel: 'party'` | Someone wrote in the bot's party chat. |
| `Events.FriendMessage` | `Message` with `channel: 'friend'` | An Epic friend whispered the bot. |

`message.bot` is the bot that received it. `message.author` is `{ id, displayName }`. `message.reply(text)` sends back on the same channel: party chat, or a whisper to the author.

## Friends

| Event | Extra fields |
| :--- | :--- |
| `Events.FriendRequest` | `{ id, displayName }` |
| `Events.FriendAdded` | The user is now on the friend list. |
| `Events.FriendRemoved` | The user left the friend list. |
| `Events.FriendOnline` / `Events.FriendOffline` | Presence came online or went offline. |
| `Events.FriendPresence` | `status`, `isJoinable`, `partySize` |
| `Events.UserBlocked` / `Events.UserUnblocked` | The bot blocked or unblocked a user. |

Accept or decline a request with `bot.acceptFriend` and `bot.declineFriend`. See [Chat and commands](/docs/sdk/chat-and-commands.md#friends).

## Party

| Event | Extra fields |
| :--- | :--- |
| `Events.PartyInvite` | `partyId`, `sender` |
| `Events.PartyJoinRequest` | `partyId`, `sender` |
| `Events.PartyMemberJoined` | `{ member }` with cosmetic ids, not the meta schema |
| `Events.PartyMemberLeft` | The member who left |
| `Events.PartyMemberKicked` | The member who was kicked |
| `Events.PartyMemberPromoted` | The new party leader |
| `Events.PartyMemberUpdated` | Member summary after a cosmetic or matchmaking tick |
| `Events.PartyUpdate` | `id`, `size`, `memberIds` |
| `Events.PartyRecreated` | The bot made a new party after the previous one was disbanded |

## Cosmetics and match

These fire when one field on a member changes. `value` is the new value and `previousValue` is the old one, when the client has it.

| Event | What changed |
| :--- | :--- |
| `Events.PartyMemberOutfitUpdated` | Outfit |
| `Events.PartyMemberEmoteUpdated` | Emote, emoji, or jam track |
| `Events.PartyMemberBackpackUpdated` | Back bling |
| `Events.PartyMemberPickaxeUpdated` | Pickaxe |
| `Events.PartyMemberReadinessUpdated` | `value` is the new ready boolean |
| `Events.PartyMemberMatchStateUpdated` | Match state |

The full list, including payload shapes, is [`Events`](/sdk?symbol=Events) in the SDK reference. Chat payloads are [`Message`](/sdk?symbol=Message). The ready payload is [`Bot`](/sdk?symbol=Bot).

## A listener that acts

Register before `start()`. `ready` is the first safe place to touch that bot's party. Invites and friend requests include the sender so you can accept without listing pending friends first.

```ts
import FNLB, { Events } from 'fnlb';

const fnlb = new FNLB();

fnlb.on(Events.Ready, async (bot) => {
  console.log(bot.displayName, bot.party.id);
});

fnlb.on(Events.FriendRequest, async ({ bot, id }) => {
  await bot.acceptFriend(id);
});

fnlb.on(Events.PartyInvite, async ({ bot, sender }) => {
  console.log(sender.displayName, 'invited', bot.nickname);
});

fnlb.on(Events.PartyMemberOutfitUpdated, ({ member, value }) => {
  console.log(member.displayName, 'equipped', value);
});

await fnlb.start({
  token: 'FNLB_...',
  categories: ['your-category-id']
});
```

`fnlb.once(Events.Ready, ...)` runs for the first bot only. Use `on` when more than one bot will log in.

`PartyMemberJoined` and `PartyMemberUpdated` carry a member summary: id, display name, leader, ready, and cosmetic ids. They do not include the meta schema. Read that with `bot.party.meta.get()` or `member.meta.get()`, documented in [Bots and parties](/docs/sdk/parties.md#meta).

Cosmetic events are the ones to use when you want to react to a change. Setting an outfit yourself with `party.setOutfit` also updates the member and can emit `PartyMemberOutfitUpdated`.

## Reference

| Topic | Symbol |
| :--- | :--- |
| Event names | [`Events`](/sdk?symbol=Events) |
| Chat message | [`Message`](/sdk?symbol=Message#reply) |
| Ready bot | [`Bot`](/sdk?symbol=Bot) |
| Shard hello | [`Shard`](/sdk?symbol=Shard) |
