Bot API docs

discord.js, discord.py and HTTP

Discord libraries talk to Discord's addresses unless you tell them otherwise. Each one needs Voicaw's REST address, gateway address and (for pictures) CDN address.

discord.js

Checked with discord.js 14.27: logging in, events, member lists, replies with embeds, edits, reactions, pins, file uploads, roles (including moving them), channels and threads, and slash commands, buttons, selects and forms (see Commands and components). discord.js asks the API where the gateway is, so the rest option is all it needs.

import { Client, GatewayIntentBits, EmbedBuilder } from 'discord.js';

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMembers,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.GuildMessageReactions,
    GatewayIntentBits.MessageContent,
  ],
  rest: {
    api: 'https://api.voicaw.com/api',
    cdn: 'https://api.voicaw.com/api/cdn',
  },
});

client.once('ready', () => console.log(`Logged in as ${client.user.tag}`));

client.on('messageCreate', async (message) => {
  if (message.author.bot || message.content !== '!weather') return;
  await message.reply({
    embeds: [new EmbedBuilder().setTitle('Today').setDescription('Sunny, 21°').setColor(0xffcc00)],
  });
});

client.login(process.env.VOICAW_TOKEN);

discord.py

Set the gateway address too. discord.py doesn't ask the API where the gateway is: it connects to Discord's own gateway, wss://gateway.discord.gg. Without the DEFAULT_GATEWAY line below, your bot sends its Voicaw token to Discord.

Checked with discord.py 2.7.1 (with its default compressed gateway): logging in, the guild cache, messages, embeds, reactions, edits, history and deleting, and app commands, views and modals (see Commands and components). Set these before the client starts:

import os
import discord, yarl
from discord.http import Route

Route.BASE = 'https://api.voicaw.com/api/v10'
discord.gateway.DiscordWebSocket.DEFAULT_GATEWAY = yarl.URL('wss://api.voicaw.com/api/gateway/')
discord.asset.Asset.BASE = 'https://api.voicaw.com/api/cdn'

intents = discord.Intents.default()
intents.message_content = True
client = discord.Client(intents=intents)

@client.event
async def on_message(message):
    if message.author.bot:
        return
    if message.content == '!ping':
        await message.channel.send('pong')

client.run(os.environ['VOICAW_TOKEN'])

Other libraries

Anything that lets you change Discord's API address, gateway address and CDN address should work. Check which addresses it uses before giving it your token: some libraries connect to gateway.discord.gg without asking GET /gateway/bot, like discord.py does.

Plain HTTP

Every request carries the bot's token:

curl https://api.voicaw.com/api/v10/users/@me \
  -H "Authorization: Bot $VOICAW_TOKEN"

curl https://api.voicaw.com/api/v10/channels/42/messages \
  -H "Authorization: Bot $VOICAW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content": "Hello from curl", "embeds": [{"title": "Hi", "color": 5793266}]}'

Files go as multipart/form-data, with the message's JSON in payload_json and the files as files[0], files[1]…, as on Discord.

Pictures

Libraries build picture links from Discord's CDN paths. Voicaw answers the ones they use (/avatars/<user>/<hash>.png, /icons/<guild>/<hash>.png, /emojis/<id>.png) at https://api.voicaw.com/api/cdn by redirecting to the picture. Users and guilds also carry the picture's address as avatar_url and icon_url, which aren't Discord's.