Skip to main content
The @packages/discord-api package provides type-safe Discord API wrappers built with Effect and automatically generated from Discord’s OpenAPI specification.

Installation

npm install @packages/discord-api

Overview

This package provides:
  • Auto-generated types from Discord OpenAPI spec
  • Effect-based API for type-safe requests
  • Schema validation using Effect Schema
  • Type-safe Discord models (users, guilds, channels, etc.)

Auto-Generated Types

All types are generated from Discord’s OpenAPI specification:
import * as Discord from "@packages/discord-api/generated";

// Discord models with full type safety
type User = Discord.UserResponse;
type Guild = Discord.GuildResponse;
type Channel = Discord.ChannelResponse;
type Message = Discord.MessageResponse;

Core Types

Snowflake Type

import { SnowflakeType } from "@packages/discord-api/generated";

// Discord snowflake IDs
const userId: SnowflakeType = "123456789012345678";
const guildId: SnowflakeType = "987654321098765432";
SnowflakeType
string
Discord snowflake ID (string matching pattern ^(0|[1-9][0-9]*)$)

UserResponse

import { UserResponse } from "@packages/discord-api/generated";

const user: UserResponse = {
  id: "123456789012345678",
  username: "example_user",
  discriminator: "0",
  avatar: "a_abc123...",
  global_name: "Example User",
  public_flags: 0,
  flags: 0,
};
id
SnowflakeType
required
User’s unique Discord ID
username
string
required
User’s username
discriminator
string
required
User’s 4-digit discriminator (deprecated, now “0”)
avatar
string | null
Avatar hash
global_name
string | null
User’s display name
bot
boolean | null
Whether the user is a bot
system
boolean | null
Whether the user is an official Discord system user
banner
string | null
Banner hash
accent_color
number | null
Banner color as integer
public_flags
number
required
Public flags on user’s account
flags
number
required
Flags on user’s account

OAuth2 Scopes

import { OAuth2Scopes } from "@packages/discord-api/generated";

const scopes: OAuth2Scopes[] = [
  "identify",
  "email",
  "guilds",
  "guilds.members.read",
  "bot",
  "applications.commands",
];
Available scopes:
  • identify - /users/@me without email
  • email - /users/@me with email
  • guilds - /users/@me/guilds
  • guilds.members.read - Read guild member data
  • bot - Add bot to guilds
  • applications.commands - Use application commands
  • Many more (see Discord documentation)

ApplicationOAuth2InstallParamsResponse

import { ApplicationOAuth2InstallParamsResponse } from "@packages/discord-api/generated";

const installParams: ApplicationOAuth2InstallParamsResponse = {
  scopes: ["applications.commands", "bot"],
  permissions: "8", // Administrator
};
scopes
array
required
Array of OAuth2 scopes (“applications.commands” | “bot”)
permissions
string
required
Permission bitfield as string

Effect Schema Integration

All types are Effect Schema classes:
import { Schema as S } from "effect";
import { UserResponse } from "@packages/discord-api/generated";
import { Effect } from "effect";

// Parse and validate Discord user data
const parseUser = (data: unknown) =>
  Effect.gen(function* () {
    const user = yield* S.decodeUnknown(UserResponse)(data);
    return user;
  });

// Use in your application
const result = await Effect.runPromise(
  parseUser({
    id: "123456789",
    username: "test",
    discriminator: "0",
    public_flags: 0,
    flags: 0,
  })
);

Common Patterns

Type-Safe API Calls

import { UserResponse, SnowflakeType } from "@packages/discord-api/generated";
import { Effect, Schema as S } from "effect";

const getDiscordUser = (userId: SnowflakeType) =>
  Effect.gen(function* () {
    const response = yield* Effect.tryPromise(() =>
      fetch(`https://discord.com/api/v10/users/${userId}`, {
        headers: {
          Authorization: `Bot ${process.env.DISCORD_BOT_TOKEN}`,
        },
      })
    );
    
    const data = yield* Effect.tryPromise(() => response.json());
    const user = yield* S.decodeUnknown(UserResponse)(data);
    
    return user;
  });

Validate Webhook Payloads

import { MessageResponse } from "@packages/discord-api/generated";

const validateMessage = (payload: unknown) =>
  S.decodeUnknownSync(MessageResponse)(payload);

// In webhook handler
app.post("/webhook", (req, res) => {
  try {
    const message = validateMessage(req.body);
    // Process validated message
  } catch (error) {
    res.status(400).send("Invalid payload");
  }
});

Generating Types

The package includes scripts to regenerate types from Discord’s OpenAPI spec:
# Sync latest OpenAPI spec from Discord
bun run sync

# Generate TypeScript types
bun run gen

# Do both
bun run update

Generated Files

src/generated.ts
file
Auto-generated TypeScript types and Effect Schema classes
open-api.json
file
Discord OpenAPI specification

Exports

./generated
module
All auto-generated Discord API types and schemas

Example: Bot Integration

import { UserResponse, OAuth2Scopes } from "@packages/discord-api/generated";
import { Effect, Schema as S } from "effect";

class DiscordBot {
  constructor(private token: string) {}
  
  getCurrentUser() {
    return Effect.gen(function* () {
      const response = yield* Effect.tryPromise(() =>
        fetch("https://discord.com/api/v10/users/@me", {
          headers: { Authorization: `Bot ${this.token}` },
        })
      );
      
      const data = yield* Effect.tryPromise(() => response.json());
      const user = yield* S.decodeUnknown(UserResponse)(data);
      
      return user;
    });
  }
}

const bot = new DiscordBot(process.env.DISCORD_BOT_TOKEN!);
const user = await Effect.runPromise(bot.getCurrentUser());
console.log(user.username);

Benefits

  • Type Safety: Catch Discord API errors at compile time
  • Auto-Updated: Regenerate types when Discord updates their API
  • Effect Integration: Works seamlessly with Effect for error handling
  • Schema Validation: Validate API responses at runtime
  • IntelliSense: Full autocomplete for Discord API types

Dependencies

  • @effect/platform - Effect HTTP client
  • effect - Effect library for functional programming
  • @tim-smart/openapi-gen - OpenAPI type generation