HTTP Client
fnlb.api is created inside start(), using the same token. It calls https://api.fnlb.net/v1. Set apiBaseUrl on the FNLB constructor to point somewhere else. OAuth tokens still need the scope each route requires. See OAuth2 and the API reference for the route list. Limits are the same per-route limits as a direct HTTP call. See Rate limits. A non-2xx response throws ApiError. status is the HTTP status, path is the route, and body is the parsed error payload.
import FNLB, { ApiError } from 'fnlb';
const fnlb = new FNLB();
await fnlb.start({ token: 'FNLB_...', categories: ['your-category-id'] });
try {
const user = await fnlb.api.user.get({ includeEmail: true });
const bots = await fnlb.api.bots.list();
console.log(user.username, bots.length);
} catch (error) {
if (error instanceof ApiError) console.error(error.status, error.body);
}Account
| Call | What it does |
|---|---|
api.user.get() | The account that owns the token. includeEmail: true adds the email when the token may read it. |
api.bots.list() / get(id) | Every bot on the account, including ones this process is not running. |
api.bots.create / update / delete | Change bots. |
api.bots.stats() | Counts for the account. |
api.bots.bulkExport / bulkImport | Move device auth in bulk. Same limits as the bulk guide. |
api.categories.list / get / create / update / delete | Categories. delete(id, { includeBots: true }) also deletes bots in that category. |
api.presets.list / get / create / update / delete | Cosmetic presets. Creating and listing presets requires a VIP account, or staff. |
Commands and chat
Cloud commands work for a bot that is not running in this process. Local bot.runCommand does not round-trip through the API.
const bots = await fnlb.api.bots.list();
const id = bots[0].id;
await fnlb.api.bots.commands.run(id, { command: 'outfit', args: ['renegade'] });
await fnlb.api.bots.chat.send(id, { content: 'hello from the api' });chat.send sends one line and waits for the bot's reply text. It is not party meta and it is not the local Message event.
Friends and party snapshot
These routes read a bot that is connected to FNLB. They are not the local IPC friends list.
await fnlb.api.bots.friends.list(botId);
await fnlb.api.bots.friends.pending(botId);
await fnlb.api.bots.users.search(botId, 'name');
await fnlb.api.bots.users.blocked(botId);
await fnlb.api.bots.party.member(botId, memberId);party.member is the cosmetic snapshot from the API, not bot.party.me.meta.
Creating a bot
create stores Epic device auth. All three device fields are required. parent is the category id.
const created = await fnlb.api.bots.create({
nickname: 'Alpha',
parent: 'category-id',
deviceAuth: {
accountId: 'epic-account-id',
deviceId: 'device-id',
secret: 'device-secret'
}
});
await fnlb.api.bots.update(created.id, { disabled: false });update accepts nickname, email, parent (null removes the category), disabled, and a replacement deviceAuth. delete removes that bot. categories.delete(id, { includeBots: true }) also deletes the bots in the category. bulkExport({ deleteAfterExport: false }) returns device auth for the account. bulkImport writes a list back. Both follow the bulk operations limits. Treat the secret as a credential.
Scopes
An API token can call the routes that token is allowed to call. An OAuth access token needs the scope on the route. The usual ones for this client:
| Work | Scopes |
|---|---|
start() | bots.run, categories.read, bots.read |
| List and edit bots | bots.read, bots.write |
| Categories | categories.read, categories.write |
| Cloud command or chat | The bots scope that route documents in the API reference |
A missing scope is ApiError with status 401 or 403. body is the API error payload.
Reference
| Topic | Where |
|---|---|
| Client | RestClient |
| Thrown error | ApiError |
| Bot record | ApiBot |
| Command reply | ApiCommandResult |
| Route list and scopes | API reference |
| Local equivalent of commands and chat | Chat and commands |