REST
REST is Lunibee’s HTTP client for the Discord REST API. It handles per-route rate limiting, global rate limits, exponential backoff, and cancellation via AbortSignal.
Import
Section titled “Import”import { REST, Routes } from "lunibee";// or directly:import { REST, Routes } from "@lunibee/rest";import { REST, Routes } from "lunibee";// or directly:import { REST, Routes } from "@lunibee/rest";Constructor
Section titled “Constructor”new REST(options: RESTOptions)new REST(options )| Option | Type | Description |
|---|---|---|
token |
string |
Discord bot token. |
apiVersion |
number |
API version (default: 10). |
baseURL |
string |
Override the Discord base URL. |
const rest = new REST({ token: process.env.DISCORD_TOKEN! });const rest = new REST({ token: process.env.DISCORD_TOKEN });Methods
Section titled “Methods”All methods accept an optional RESTRequestOptions object as the last argument.
get<T>(path, options?)
Section titled “get<T>(path, options?)”const user = await rest.get<APIUser>(Routes.user("@me"));const user = await rest.get<APIUser>(Routes.user("@me"));post<T>(path, body?, options?)
Section titled “post<T>(path, body?, options?)”Accepts the body directly or as { body: ... } (Discord.js-familiar form):
// Direct body (Lunibee canonical):const message = await rest.post(Routes.channelMessages(channelId), { content: "Hello!" });
// Discord.js-familiar:const message = await rest.post(Routes.channelMessages(channelId), { body: { content: "Hello!" } });// Direct body (Lunibee canonical):const message = await rest.post(Routes.channelMessages(channelId), { content: "Hello!" });
// Discord.js-familiar:const message = await rest.post(Routes.channelMessages(channelId), { body: { content: "Hello!" } });patch<T>(path, body?, options?)
Section titled “patch<T>(path, body?, options?)”await rest.patch(Routes.channel(channelId), { name: "new-name" });await rest.patch(Routes.channel(channelId), { name: "new-name" });put<T>(path, body?, options?)
Section titled “put<T>(path, body?, options?)”await rest.put(Routes.guildBan(guildId, userId), { delete_message_seconds: 86400 });await rest.put(Routes.guildBan(guildId, userId), { delete_message_seconds: 86400 });delete<T>(path, options?)
Section titled “delete<T>(path, options?)”await rest.delete(Routes.message(channelId, messageId));await rest.delete(Routes.message(channelId, messageId));postWithFiles<T>(path, body, files, options?)
Section titled “postWithFiles<T>(path, body, files, options?)”Sends a multipart/form-data request with file attachments.
await rest.postWithFiles( Routes.channelMessages(channelId), { content: "Here is your file!" }, [{ name: "report.csv", data: csvBuffer, contentType: "text/csv" }],);await rest.postWithFiles( Routes.channelMessages(channelId), { content: "Here is your file!" }, [{ name: "report.csv", data , contentType: "text/csv" }],);setToken(token)
Section titled “setToken(token)”Updates the token used for subsequent requests.
Routes — Path Helpers
Section titled “Routes — Path Helpers”Routes provides strongly-typed path builders for every Discord API endpoint:
Routes.user("@me") // "/users/@me"Routes.channel(channelId) // "/channels/{id}"Routes.channelMessages(channelId) // "/channels/{id}/messages"Routes.message(channelId, messageId) // "/channels/{id}/messages/{messageId}"Routes.guild(guildId) // "/guilds/{id}"Routes.guildChannels(guildId) // "/guilds/{id}/channels"Routes.guildMember(guildId, userId) // "/guilds/{id}/members/{userId}"Routes.guildBan(guildId, userId) // "/guilds/{id}/bans/{userId}"Routes.guildRoles(guildId) // "/guilds/{id}/roles"Routes.interactionCallback(id, token) // "/interactions/{id}/{token}/callback"Routes.user("@me") // "/users/@me"Routes.channel(channelId) // "/channels/{id}"Routes.channelMessages(channelId) // "/channels/{id}/messages"Routes.message(channelId, messageId) // "/channels/{id}/messages/{messageId}"Routes.guild(guildId) // "/guilds/{id}"Routes.guildChannels(guildId) // "/guilds/{id}/channels"Routes.guildMember(guildId, userId) // "/guilds/{id}/members/{userId}"Routes.guildBan(guildId, userId) // "/guilds/{id}/bans/{userId}"Routes.guildRoles(guildId) // "/guilds/{id}/roles"Routes.interactionCallback(id, token) // "/interactions/{id}/{token}/callback"AbortSignal & Cancellation
Section titled “AbortSignal & Cancellation”const controller = new AbortController();setTimeout(() => controller.abort(), 5000); // cancel after 5s
try { const data = await rest.get(Routes.guild(guildId), { signal: controller.signal });} catch (error) { if (error instanceof RESTError && error.name === "AbortError") { console.warn("Request was cancelled."); }}const controller = new AbortController();setTimeout(() => controller.abort(), 5000); // cancel after 5s
try { const data = await rest.get(Routes.guild(guildId), { signal: controller.signal });} catch (error) { if (error instanceof RESTError && error.name === "AbortError") { console.warn("Request was cancelled."); }}RESTError
Section titled “RESTError”Thrown when Discord returns a non-2xx response.
import { RESTError } from "lunibee";
try { await rest.delete(Routes.message(channelId, messageId));} catch (error) { if (error instanceof RESTError) { console.error(`Discord API Error ${error.status}: ${error.message}`); console.error("Code:", error.code); // Discord error code console.error("Method:", error.method); // "DELETE" console.error("Path:", error.path); // "/channels/.../messages/..." }}import { RESTError } from "lunibee";
try { await rest.delete(Routes.message(channelId, messageId));} catch (error) { if (error instanceof RESTError) { console.error(`Discord API Error ${error.status}: ${error.message}`); console.error("Code:", error.code); // Discord error code console.error("Method:", error.method); // "DELETE" console.error("Path:", error.path); // "/channels/.../messages/..." }}Full Example
Section titled “Full Example”Fetch a user and send a DM
import { REST, Routes } from "lunibee";
const rest = new REST({ token: process.env.DISCORD_TOKEN! });
// Fetch a userconst user = await rest.get(Routes.user("123456789012345678"));
// Open a DM channelconst dmChannel = await rest.post(Routes.userChannels(), { recipient_id: "123456789012345678" });
// Send a messageawait rest.post(Routes.channelMessages((dmChannel as any).id), { content: "Hello from Lunibee REST! 🐝",});import { REST, Routes } from "lunibee";
const rest = new REST({ token: process.env.DISCORD_TOKEN });
// Fetch a userconst user = await rest.get(Routes.user("123456789012345678"));
// Open a DM channelconst dmChannel = await rest.post(Routes.userChannels(), { recipient_id: "123456789012345678" });
// Send a messageawait rest.post(Routes.channelMessages((dmChannel as any).id), { content: "Hello from Lunibee REST 🐝",});