Skip to content

REST requests and rate limits ​

Most manager methods ultimately use Altkit's REST layer. It builds Discord API routes, serializes payloads, queues requests by rate-limit bucket, retries selected failures, and converts error responses into structured errors.

Prefer public managers and structures ​

Use documented high-level methods when one exists:

js
const channel = await client.channels.fetch(process.env.CHANNEL_ID);
await channel.send('Hello');

The internal client.api router is private. Calling undocumented routes directly couples an application to internal routing syntax and unversioned Discord behavior.

Error classes ​

REST operations can reject with:

  • DiscordAPIError for a Discord JSON error response;
  • HTTPError for a non-Discord HTTP failure;
  • RateLimitError when rejectOnRateLimit selects the route;
  • transport or timeout errors from the underlying request stack.
js
const { DiscordAPIError, HTTPError, RateLimitError } = require('@altkit/discord');

try {
  await channel.send('Hello');
} catch (error) {
  if (error instanceof RateLimitError) {
    console.warn('The configured route rejected instead of queueing');
  } else if (error instanceof DiscordAPIError || error instanceof HTTPError) {
    console.error(error.name, error.message);
  } else {
    throw error;
  }
}

Automatic rate-limit handling ​

By default, the REST manager waits for a bucket or global rate limit and resumes queued work. Do not add an immediate retry loop around every HTTP 429; that competes with the queue and increases request volume.

Listen for rate-limit diagnostics when investigating throughput:

js
client.on('rateLimit', data => {
  console.warn({
    route: data.route,
    timeout: data.timeout,
    global: data.global,
  });
});

Reject selected rate limits ​

ClientOptions.rejectOnRateLimit can be a list of route prefixes or a predicate. Matching requests throw RateLimitError instead of waiting.

js
const client = new Client({
  rejectOnRateLimit: ['/channels'],
});

This is useful when stale work should be abandoned, but it moves retry and user-feedback responsibility into the application.

Invalid-request warnings ​

Discord tracks certain invalid requests separately from normal rate limits. Configure invalidRequestWarningInterval to receive periodic warnings:

js
const client = new Client({
  invalidRequestWarningInterval: 100,
});

client.on('invalidRequestWarning', data => {
  console.warn(data);
});

A warning is a signal to fix the request source—not to increase retry limits.

Timeouts, retries, and offsets ​

Relevant client options include:

OptionPurpose
restRequestTimeoutCancel a request that takes too long
retryLimitBound retries for eligible server failures
restTimeOffsetAdd timing tolerance before a bucket resumes
restGlobalRateLimitApply an application-level global request limit
restSweepIntervalRemove inactive request buckets periodically

Use conservative values and measure. Raising a retry limit cannot fix invalid credentials, forbidden actions, malformed payloads, or missing resources.

High-frequency diagnostics ​

apiRequest and apiResponse may emit multiple times for one logical request and can be extremely noisy. Filter by route and redact sensitive payloads:

js
client.on('apiResponse', (request, response) => {
  if (!request.path.startsWith('/channels/')) return;
  console.debug(request.method, request.path, response.status);
});

Never log authorization headers, webhook tokens, TOTP values, or full authentication payloads.

Proxies ​

REST proxy configuration lives under http.agent; gateway proxy configuration lives under ws.agent. A proxy changes the trust and failure boundaries but does not bypass Discord rate limits.

See client configuration and security.

Useful API pages ​

Unofficial software. Not affiliated with or supported by Discord.