Commands
All commands require authentication except auth. listener is valid on every request and is omitted from the field lists below. “Broadcast” means other relevant connections may receive the event.
Session and discovery
Section titled “Session and discovery”| Command | Request fields | Response or event |
|---|---|---|
auth |
validator: string |
auth_success, then ready; or auth_error |
capabilities |
capabilities: string[] (or legacy val) |
No response; strings are stored on the connection |
ping |
sent_at?: number |
Without a positive sent_at: { cmd, server_time }; otherwise echoes it and adds receive/send timestamps |
typing |
channel?, thread_id?, duration: integer >= 0 = 6000, sent_at?: number |
Broadcast typing; duration is forwarded unchanged with no server-side unit conversion |
The server-originated handshake is not a request. channel_get, unreads_update, user_join, user_connect, user_disconnect, ready, auth_success, auth_error, and rate_limit are also server events or response shapes rather than dispatched requests. Presence changes reuse the dispatched name status_get as their event command.
Channels
Section titled “Channels”| Command | Request fields | Response or event |
|---|---|---|
channels_get |
none | channels_get { val: Channel[] } |
channel_create |
name (1–64), type (text|voice|forum|separator); optional permissions, description, display_name, size, max_message_age, slow_mode_cooldown. For separators, size is UI padding/spacing. |
{ cmd, val: true }; channel refresh is pushed |
channel_update |
current_name, updates containing any create field |
{ cmd, val: true }; focused/full refresh is pushed |
channel_move |
name, position: integer >= 0 |
{ cmd, val: true } |
channel_delete |
name |
{ cmd, val: true } |
Channel names are validated by the shared channel helper. Metadata mutations are persisted, audited, then followed by channel refreshes.
Messages
Section titled “Messages”For message commands, supply either channel or thread_id. When a thread is supplied, the server derives and returns its parent channel.
| Command | Request fields | Response or event |
|---|---|---|
message_new |
channel?, thread_id?, and at least one of content, embeds, attachments; optional reply_to, ping; optional signature fields |
Broadcast message_new { channel, thread_id?, message } |
message_get |
channel?, thread_id?, id |
message_get { channel, thread_id?, message } |
message_replies |
channel?, thread_id?, id |
message_replies { channel, thread_id?, val } |
messages_get |
channel?, thread_id?, start: number|string = 0, limit = 100 |
Returns the newest start + limit messages; current code does not trim to limit or treat start as an offset |
messages_around |
channel?, thread_id?, around, bounds?: { above=50, below=50 } |
{ messages, range, at_start?, at_end? }; each bound capped at 200 |
messages_search |
query?, fuzzy?, channel?, thread_id?, filters?, limit?, offset? |
{ results, total, offset, limit, has_more, fuzzy } |
message_edit |
channel?, thread_id?, id; any of content, embeds, attachments; optional signature fields |
Broadcast message_edit { id, channel, thread_id?, message } |
message_delete |
channel?, thread_id?, id |
Broadcast message_delete { id, channel, thread_id? } |
message_pin / message_unpin |
channel?, thread_id?, id |
Broadcast pin-change event |
messages_pinned |
channel?, thread_id? |
{ messages: Message[] } |
Signature fields are author_id, key_id, signature, and timestamp. Search filters support from, mentions, mentions_role, pinged, has, pinned, edited, before, and after. has accepts attachment, embed, reaction, reply, edit, webhook, command, image, video, audio, poll, link, or mention.
| Command | Request fields | Response or event |
|---|---|---|
poll_create |
channel?, thread_id?, question, options, optional multiselect/expiry fields |
Broadcast message_new with poll_id and poll embed |
poll_get |
poll identifier/context accepted by pollRequest |
poll_get { poll } |
poll_vote |
poll context plus option_id or option_ids |
Broadcast { poll_id, message_id, user, option_ids, results } |
poll_results |
poll context | { poll_id, message_id, results } |
poll_end |
poll context | Broadcast { poll_id, message_id, channel, results } |
For multiselect polls, sending one option_id toggles that choice relative to the user’s current selection; option_ids replaces the selection.
Threads and unreads
Section titled “Threads and unreads”| Command | Request fields | Response or event |
|---|---|---|
threads_get |
channel (forum) |
{ channel, val: Thread[] } |
thread_create |
channel, name |
Broadcast { thread, channel } |
thread_get |
thread_id |
{ thread } |
thread_update |
thread_id; optional name, archived, locked |
Broadcast { thread, channel } |
thread_delete |
thread_id |
Broadcast { thread_id, channel } |
thread_join / thread_leave |
thread_id |
Broadcast { thread, thread_id, user, channel } |
thread_pin / thread_unpin |
thread_id |
Broadcast pin-change event |
unreads_get |
none | { channels, threads, … } unread snapshot |
unreads_ack |
channel, optional thread_id, optional message_id |
Direct acknowledgement and unreads_update |
pings_get |
pagination/context fields | Stored ping records visible to the user |
Threads can only be created/listed in forum channels. Their messages use the ordinary message commands with thread_id.
Users and moderation
Section titled “Users and moderation”| Command | Request fields | Response or event |
|---|---|---|
users_online |
none | { users: PublicUser[] } |
users_list |
none | { users: PublicUser[] } excluding banned users |
users_banned |
none | { users: string[] } |
status_get |
user |
status { username, status } |
status_set |
status, text? (max 100) |
{ status } and presence broadcast |
user_update |
user, updates: { username?, nickname? } |
Broadcast { user, nickname } |
user_ban / user_unban |
user |
{ user, banned|unbanned } |
user_kick |
user, reason? |
Broadcast { user, kicked: true }; target receives auth_error |
user_timeout |
user, duration > 0 seconds, reason? |
{ user, timed_out: true, duration }; current code broadcasts rate_limit to all except the actor and sends it to the target a second time |
user_leave |
delete_messages?: boolean |
{ user, messages_deleted, val } |
Valid statuses are online, idle, dnd, offline, and invisible.
| Command | Request fields | Response or event |
|---|---|---|
roles_list |
none | { val: Record<string, Role> } |
role_create |
name; optional description, color, gradient, permissions, hoisted, self_assignable, category |
{ val: true, id, name } and broadcast |
role_update |
id? or name?, plus update fields |
{ val: true, id, name } and broadcast |
role_delete |
id? or name? |
{ val: true, id, name } and broadcast |
role_reorder |
roles: string[] |
{ val: true, roles } and broadcast |
user_roles_get |
user |
{ user, roles, color, gradient } |
user_roles_set |
user, roles (non-empty) |
user_roles_get response/broadcast plus target channel refresh |
self_roles_list |
none | { roles }, each with assigned |
self_role_add / self_role_remove |
role |
self-role response plus channel refresh |
An actor cannot assign a permission they do not hold. Role hierarchy and protected system-role rules are enforced in helpers.
Reactions, emoji, and stickers
Section titled “Reactions, emoji, and stickers”| Command | Request fields | Response or event |
|---|---|---|
reaction_add / reaction_remove |
message context plus reaction identifier | Broadcast reaction change |
message_react_add / message_react_remove |
same | Legacy aliases |
emoji_list |
none | { emojis } |
emoji_get |
emoji_id |
asset fields |
emoji_add |
name, image |
asset fields plus added: true |
emoji_update |
emoji_id, at least one of name, image |
asset fields plus updated |
emoji_delete |
emoji_id |
{ id, deleted } |
sticker_list |
none | { stickers } |
sticker_get |
sticker_id |
asset fields |
sticker_add |
name, image, description? |
asset fields plus added: true |
sticker_update |
sticker_id, any of name, image, description |
asset fields plus updated |
sticker_delete |
sticker_id |
{ id, deleted } |
image is the asset payload format accepted by the asset backend. File extensions must match handshake upload allowlists.
Attachments
Section titled “Attachments”| Command | Request fields | Response or event |
|---|---|---|
attachment_get |
attachment_id |
attachment_info |
attachment_list |
none | attachment_list (requires manage_server) |
attachment_delete |
attachment_id |
attachment_deleted |
Upload is HTTP rather than WebSocket; see HTTP & uploads.
Slash commands and voice
Section titled “Slash commands and voice”| Command | Request fields | Response or event |
|---|---|---|
slash_list |
channel?, thread_id? |
{ val: command definitions } |
slash_call |
command, args, channel?, thread_id?, optional username |
response/event defined by command |
slash_register |
commands |
add/remove events and registration result |
slash_response |
id, response |
response delivery acknowledgement |
voice_join |
channel, peer_id |
Broadcast voice state/join event |
voice_leave |
current voice context | Broadcast leave event |
voice_mute / voice_unmute |
current voice context | Broadcast mute state |
voice_state |
channel |
{ channel, state } |
Voice signaling is peer-state coordination; media transport is a client concern.
Reports, audit log, server, and webhooks
Section titled “Reports, audit log, server, and webhooks”| Command | Request fields | Response or event |
|---|---|---|
report_create |
report target/type/context fields | created report |
report_list |
filters/pagination | report collection |
report_resolve |
report identifier and resolution fields | resolved report |
modlog_get |
filters/pagination | audit records; requires audit permission in handler |
modlog_summary |
summary filters | grouped audit summary |
config_get |
none | resolved configuration |
config_update |
updates |
persisted update result |
server_update |
supported server fields | updated server info/broadcast |
server_stats |
none | server/runtime statistics |
webhook_create |
webhook definition fields | created webhook including secret material as applicable |
webhook_get |
webhook identifier | webhook definition |
webhook_list |
none | webhook collection |
webhook_update |
identifier plus updates | updated definition |
webhook_delete |
identifier | deletion result |
webhook_regenerate |
identifier | regenerated credential/path |
Administrative mutation details are intentionally validated by their focused helpers and may evolve behind the advertised capability name. Inspect error.src and feature-detect before exposing controls.
