REST reference
Every endpoint below is at https://api.voicaw.com/api/v10, takes and gives
Discord's objects, and needs Authorization: Bot <token>. "Needs" is the
permission the bot must have there. Like everyone's on Voicaw, the bot's power only reaches
below its own highest role: it can't manage roles at or above it, or members ranked as high
as it is, and never the guild's owner. Anything not listed answers 404.
Messages
| Endpoint | Needs | Notes |
GET /channels/{channel}/messages | View Channel | limit 1–100 (50), and before, after or around. Newest first. |
GET /channels/{channel}/messages/{message} | View Channel | |
POST /channels/{channel}/messages | Send Messages (Send Messages in Threads in a thread) | See Sending messages. |
PATCH /channels/{channel}/messages/{message} | Its own messages only | content, embeds, components, flags, allowed_mentions, attachments (those listed are kept) and new files. |
DELETE /channels/{channel}/messages/{message} | Its own, or Manage Messages | Goes in the guild's audit log. |
POST /channels/{channel}/messages/bulk-delete | Manage Messages | messages: 2–100 ids. No two-week age limit. Ids not in the channel are skipped. |
POST /channels/{channel}/typing | Send Messages | "… is typing" for a few seconds. |
Sending messages
JSON, or multipart/form-data with payload_json and files as files[n]. A message needs content, an embed or a file.
content: the text, in Discord's markdown. Mentions are written as on Discord: <@user>, <@&role>, <#channel>, @everyone and @here (those two, and roles that aren't mentionable, need Mention Everyone). Custom emoji: <:name:id>.
embeds: up to 10, with Discord's limits (6000 characters in all, title 256, description 4096, 25 fields…). attachment://name points at a file sent with the message. Images in embeds load from their own sites in readers' apps.
- Files: up to 10, 25 MB together, stored as sent (guilds aren't encrypted).
attachments can give each a filename and description.
message_reference: a reply, to a message in the same channel. fail_if_not_exists: false sends it without the reply if that message is gone. Forwarding (type: 1) isn't supported.
allowed_mentions: parse, users, roles as on Discord.
flags: SUPPRESS_EMBEDS (4) and SUPPRESS_NOTIFICATIONS (4096, no notifications).
components: buttons and selects (see Components). A message can be only components.
nonce is given back. tts, sticker_ids, poll and enforce_nonce are ignored.
Reactions
{emoji} is the Unicode emoji (URL-encoded) or a guild emoji as name:id.
| Endpoint | Needs | Notes |
PUT /channels/{channel}/messages/{message}/reactions/{emoji}/@me | Add Reactions | Up to 20 different reactions per message. |
DELETE /channels/{channel}/messages/{message}/reactions/{emoji}/@me | | |
DELETE /channels/{channel}/messages/{message}/reactions/{emoji}/{user} | Manage Messages (unless it's the bot) | |
DELETE /channels/{channel}/messages/{message}/reactions/{emoji} | Manage Messages | Everyone's, with that emoji. |
DELETE /channels/{channel}/messages/{message}/reactions | Manage Messages | All of them. |
GET /channels/{channel}/messages/{message}/reactions/{emoji} | View Channel | Who reacted: limit 1–100 (25), after. |
Pins
| Endpoint | Needs | Notes |
GET /channels/{channel}/messages/pins | View Channel | { items: [{ pinned_at, message }], has_more }; before (a time), limit up to 50. |
GET /channels/{channel}/pins | View Channel | The older form: a list of messages. |
PUT /channels/{channel}/messages/pins/{message} | Pin Messages | Also at /channels/{channel}/pins/{message}. Up to 250 per channel. |
DELETE /channels/{channel}/messages/pins/{message} | Pin Messages | Also at /channels/{channel}/pins/{message}. |
Channels
| Endpoint | Needs | Notes |
GET /channels/{channel} | View Channel | Text and voice channels, threads and categories. |
PATCH /channels/{channel} | Manage Channels | name, topic, nsfw, parent_id (a category, or null), permission_overwrites. A thread: name and archived (see Threads). Categories can't be changed. |
DELETE /channels/{channel} | Manage Channels (Manage Messages for a thread) | Gives back the channel. Categories can't be deleted. |
PUT /channels/{channel}/permissions/{overwrite} | Manage Roles | type 0 (role) or 1 (member), allow, deny. Only permissions the bot has in the channel, only for roles below its own; bits that can't be set per channel are dropped. Not on threads (they follow their channel). |
DELETE /channels/{channel}/permissions/{overwrite} | Manage Roles | |
GET /guilds/{guild}/channels | | The channels the bot can see, and their categories. |
POST /guilds/{guild}/channels | Manage Channels | type 0 (text) or 2 (voice), name (lower-cased, spaces become dashes), topic, nsfw, parent_id, permission_overwrites. Categories can't be made. |
Threads
| Endpoint | Needs | Notes |
POST /channels/{channel}/messages/{message}/threads | Create Public Threads | name. One thread per message. |
POST /channels/{channel}/threads | Create Public Threads | name. A "started a thread" message goes in the channel. All threads are public. |
PUT /channels/{thread}/thread-members/@me | View Channel | Join. |
DELETE /channels/{thread}/thread-members/@me | | Leave. |
GET /channels/{thread}/thread-members | View Channel | |
GET /channels/{channel}/threads/archived/public | View Channel | All at once (has_more is false). |
GET /guilds/{guild}/threads/active | | In channels the bot can see. |
A thread's starter renames and archives it; so does anyone with Manage Messages, who can
also delete it. Anyone who can post in it can unarchive it, and posting does. A thread
nobody writes in for a week archives itself.
Guilds
| Endpoint | Needs | Notes |
GET /guilds/{guild} | | with_counts=true adds approximate_member_count and approximate_presence_count. |
GET /users/@me/guilds | | limit up to 200, after. |
DELETE /users/@me/guilds/{guild} | | Leave the guild. |
GET /guilds/{guild}/emojis | | The guild's custom emoji. |
GET /guilds/{guild}/emojis/{emoji} | | |
Members
| Endpoint | Needs | Notes |
GET /guilds/{guild}/members | | limit 1–1000 (1), after. |
GET /guilds/{guild}/members/search | | query (the start of a username or display name), limit 1–1000 (1). |
GET /guilds/{guild}/members/{user} | | @me for the bot. |
PATCH /guilds/{guild}/members/{user} | Manage Roles | Only roles. The bot's own role stays whether listed or not. nick, mute, deaf, channel_id and communication_disabled_until fail with 50035 (unless null). |
PUT /guilds/{guild}/members/{user}/roles/{role} | Manage Roles | |
DELETE /guilds/{guild}/members/{user}/roles/{role} | Manage Roles | |
DELETE /guilds/{guild}/members/{user} | Kick Members | Kick. |
Roles
| Endpoint | Needs | Notes |
GET /guilds/{guild}/roles | | @everyone's id is the guild's. |
GET /guilds/{guild}/roles/{role} | | |
POST /guilds/{guild}/roles | Manage Roles | name, permissions (only ones the bot has), color (or colors.primary_color), hoist, mentionable. Goes at the bottom, above @everyone. |
PATCH /guilds/{guild}/roles | Manage Roles | New positions: [{ id, position }]. @everyone stays at the bottom; roles at or above the bot's highest can't move. |
PATCH /guilds/{guild}/roles/{role} | Manage Roles | The same fields as making one. @everyone can only have its permissions changed. |
DELETE /guilds/{guild}/roles/{role} | Manage Roles | A bot's own role can't be deleted. |
Bans
| Endpoint | Needs | Notes |
GET /guilds/{guild}/bans | Ban Members | reason is always null. |
GET /guilds/{guild}/bans/{user} | Ban Members | |
PUT /guilds/{guild}/bans/{user} | Ban Members | Removes them from the guild. Their messages stay (delete_message_seconds is ignored). |
DELETE /guilds/{guild}/bans/{user} | Ban Members | 10026 if there's no ban. |
Invites
| Endpoint | Needs | Notes |
POST /channels/{channel}/invites | Create Invite | max_age in seconds (default a day, up to 30 days, 0 for none), max_uses (up to 1000, 0 for any). Voicaw's invites are to the guild: the channel is only given back. The link is https://app.voicaw.com/invite/{code}. |
GET /guilds/{guild}/invites | Manage Guild | Invites that still work (not the vanity URL). |
GET /guilds/{guild}/vanity-url | Manage Guild | { code, uses }; code is null when there's none. Only the guild's owner sets it, in the app. Also the guild's vanity_url_code. |
Scheduled events
As Discord's, with voice channel (entity_type 2) and somewhere-else (3) events;
Voicaw has no stage channels (1 is refused). privacy_level is always 2. A
voice channel's event needs View Channel there. Covers (image) are image data
(a data URI, up to 8 MB). recurrence_rule takes Discord's shapes (daily, with
or without by_weekday; weekly or every other week on one day; monthly on the
nth weekday; yearly on a date), worked out in UTC for bots; its start is
ignored (the event's start is used), and the start must be one of its days. Ended and
cancelled events are deleted; a repeating one moves on to its next occurrence. Somewhere-else
events start and end on their own at their times; voice channel events are started by hand
(status 2), cancelled if nobody starts them within 12 hours, and end once their channel has
been empty for 5 minutes.
| Endpoint | Needs | Notes |
GET /guilds/{guild}/scheduled-events | | Those the bot can see; user_count with with_user_count=true. |
POST /guilds/{guild}/scheduled-events | Create Events (and Connect in a voice channel) | The bot is interested in its own events, as a person making one is. At most 100 per guild. |
GET /guilds/{guild}/scheduled-events/{event} | | 10070 for one that's gone or hidden. |
PATCH /guilds/{guild}/scheduled-events/{event} | Manage Events, or its own with Create Events | Fields (a whole repeating series), and status: 2 starts it, 3 ends it, 4 cancels it before it starts. |
DELETE /guilds/{guild}/scheduled-events/{event} | Manage Events, or its own with Create Events | Every occurrence of a repeating one. |
GET /guilds/{guild}/scheduled-events/{event}/users | | Who's interested, by user id: limit (up to 100), before, after, with_member. |
Users and the application
| Endpoint | Needs | Notes |
GET /users/@me | | The bot. |
PATCH /users/@me | | username (renames the application too) and avatar (image data, or null). Twice an hour. |
GET /users/{user} | | Only people the bot shares a guild with. |
POST /users/@me/channels | | { "recipient_id": "…" }: opens (or finds) the DM with someone the bot shares a guild with; 50007 if it can't (no shared guild, blocked, or they turned bot DMs off). DMs aren't end-to-end encrypted. In a DM channel: GET the channel, GET messages (before, after, around, limit) and one message, POST messages (content, embeds, files; no components), PATCH and DELETE the bot's own, and typing (accepted, shows nothing). Anything else answers 50003. |
GET /applications/@me | | Also at /oauth2/applications/@me. |
Commands and interactions
See Commands and components for what each does. {application} must be the bot's own; {guild} a guild it's in (else 50001).
| Endpoint | Needs | Notes |
GET /applications/{application}/commands | | Global commands. All of these also exist under /applications/{application}/guilds/{guild}/commands. |
POST /applications/{application}/commands | | 201 new, or 200 replacing the one with the same type and name. 30032 past the limits (100 slash, 5 user, 5 message). |
PUT /applications/{application}/commands | | Bulk overwrite; same type and name keep their ids. |
GET /applications/{application}/commands/{command} | | 10063 if unknown. |
PATCH /applications/{application}/commands/{command} | | The type can't change. |
DELETE /applications/{application}/commands/{command} | | |
GET /applications/{application}/guilds/{guild}/commands/permissions | | Always empty: no per-command overrides. |
POST /interactions/{interaction}/{token}/callback | No bot token | Once, within 3 seconds. ?with_response=true. 40060 twice, 10062 late or unknown. |
POST /webhooks/{application}/{token} | No bot token | A follow-up, for 15 minutes, after the callback. The first one after a deferred reply fills it. |
GET PATCH DELETE /webhooks/{application}/{token}/messages/{message} | No bot token | @original or a follow-up's id. |
Voice
| Endpoint | Needs | Notes |
POST /channels/{channel}/voice | View Channel, Connect | Voicaw's own: a LiveKit token for the voice channel, { url, token, room, identity, expires_in, speak, listen }. See Voice. |
GET /guilds/{guild}/voice-states/{user or @me} | View Channel | A voice state, plus listening. |
PATCH /guilds/{guild}/voice-states/@me | In voice there | self_mute, self_deaf, or channel_id: null to leave. |
DELETE /guilds/{guild}/voice-states/@me | — | Leaves. |
Gateway
| Endpoint | Needs | Notes |
GET /gateway | No token | { url } |
GET /gateway/bot | | { url, shards: 1, session_start_limit } |
Pictures
At https://api.voicaw.com/api/cdn, without a token, redirecting to the picture (any size or format asked for):
| Endpoint | Notes |
GET /avatars/{user}/{hash}.png | A profile picture (the bot's too). |
GET /icons/{guild}/{hash}.png | A guild's icon. |
GET /emojis/{emoji}.png | A custom emoji. |
GET /guild-events/{event}/{hash}.png | A scheduled event's cover (those made through the bot API; covers people add in the app are encrypted, and their image is null). |