Version | Released |
---|---|
Not yet |
This document acts as a user guide to the public APIs of Decent servers as defined by the specification. If you are writing a server implementation, please refer to that document also.
Table of contents
- Transport
- Authentication
- Errors
- Permissions
- Miscellaneous
- Settings
- Emotes
- Sessions
- Messages
- Channels
- Events
- Endpoints
- Get list of channels [GET /api/channels]
- Create a channel [POST /api/channels]
- Retrieve a channel [GET /api/channels/:id]
- Rename a channel [PATCH /api/channels/:id]
- Delete a channel [DELETE /api/channels/:id]
- Mark a channel as read [POST /api/channels/:id/mark-read]
- Get messages in channel [GET /api/channels/:id/messages]
- Update channel-specific role permissions [PATCH /api/channels/:id/role-permissions]
- Get channel-specific role permissions [GET /api/channels/:id/role-permissions]
- Retrieve all pinned messages [GET /api/channels/:id/pins]
- Pin a message [POST /api/channels/:id/pins]
- Unpin a message [DELETE /api/channels/:channelID/pins/:messageID]
- Users
- Events
- Endpoints
- Fetch users [GET /api/users]
- Register (create new user) [POST /api/users]
- Retrieve a user by ID [GET /api/users/:id]
- List mentions of a user [GET /api/users/:id/mentions]
- Update user details [PATCH /api/users/:id]
- Give a role to a user [POST /api/users/:userID/roles]
- Take a role from a user [DELETE /api/users/:userID/roles/:roleID]
- Retrieve a list of a user's roles [GET /api/users/:id/roles]
- Retrieve a user by ID [GET /api/users/:id]
- Get a user's permissions [GET /api/users/:id/permissions]
- Get a user's channel-specific permissions [GET /api/users/:userID/channel-permissions/:channelID]
- Delete a user [DELETE /api/users/:id]
- Check if a username is available [GET /api/username-available/:username]
- Roles
Servers support the following two forms of transport, which are meant to be used in conjunction with eachother:
The HTTP API is accessed via /api/
. All endpoints respond in JSON, and those which take request bodies expect it to also be formatted using JSON. Server implementors may choose an appropriate HTTP status code for responses, however this must not be relied on by clients.
Messages sent to and from sockets are JSON strings, following the format { evt, data }
, where evt
is a name representing the meaning of the event, and data
is an optional property specifying any additional data related to the event.
Clients should authenticate using both of the following methods at the same time.
When a request is made to an API endpoint, the server searches for a session ID string given in the request using one of:
?sessionID
in query string (URL)sessionID
in request bodyX-Session-ID
header (recommended)
Note that if session IDs are provided more than once in a single request the request will error with REPEATED_PARAMETERS.
If a session ID is provided but invalid/expired, the request is immediately terminated with an INVALID_SESSION_ID error.
If the request requires permission(s) and a session ID is not provided or its user does not posses the expected permissions, the request is terminated with a NOT_ALLOWED error.
Note that "you" in this document typically refers to the provided session ID's related user.
Sent periodically (typically every 10 seconds) by the server, as well as immediately upon the client socket connecting. Clients should respond with a pongdata
event, as described below. No data
is sent with the event.
Should be sent from clients (unlike all other WebSocket transmissions) in response to pingdata
. Notifies the server of any information related to the particular socket. Passed data should include:
sessionID
, if the client is "logged in" or keeping track of a session ID. This is used for keeping track of which users are online.- Note
null
means 'not logged in'.
- Note
Nearly all HTTP endpoints return errors situationally. Generally, when the processing of a request errors, its response will have the error
property, which will follow the form { code, message }
. Server implementors may optionally include extra infomation in this return map, using any key other than code
or message
.
The message
property is a string of a human-readable English message briefly explaining what went wrong, and the code
is a permanent identifier string for the type of error that happened. Checking code
is useful for displaying custom messages or behavior when particular errors occur.
Error codes
Error code | Meaning |
---|---|
NOT_FOUND | The requested thing was not found |
NOT_YOURS | Your attempt to do something impactful was rejected because you are not the owner/author of the thing |
MISSING_PERMISSION | You do not have a required permission |
NO | The server does not support or does not want to fulfill your request |
ALREADY_PERFORMED | That action has already been performed |
FAILED | Something went wrong internally |
INCOMPLETE_PARAMETERS | A property is missing from the request's parameters |
REPEATED_PARAMETERS | A parameter is specified twice in the request |
INVALID_PARAMETER_TYPE | A parameter is the wrong type |
INVALID_SESSION_ID | There is no session with the provided session ID |
INVALID_NAME | Provided name is invalid |
NAME_ALREADY_TAKEN | The passed name is already used by something else |
SHORT_PASSWORD | Password is too short |
INCORRECT_PASSWORD | Incorrect password |
Permissions in Decent are a way to limit and grant certain abilities to users.
How permissions work
Permissions are stored within a map of keys (representing individual permissions) to boolean values (or undefined). For example, the following permissions object describes being able to read but not send messages:
{
"readMessages": true,
"sendMessages": false
}
Individual permissions are passed according to a cascade of roles. If two or more permission objects are applied (typically based on the roles a user has), then individual permissions are determined by the most prioritized roles. For example, consider these three permission objects:
{
"sendMessages": false
}
{
"readMessages": true,
"sendMessages": true
}
{
"readMessages": false,
"sendMessages": false
}
Suppose we consider the first, top-most object to have the greatest priority, and that the second and third each in turn have less priority.
If all three permission objects are applied to a user, then to calculate the user's permissions, we start by looking at the most prioritized object. This object contains one property, sendMessages: false
. From this, we know that the user is not permitted to send messages; this is absolutely true, regardless of any other permission objects, since this object is the most prioritized one.
Then we move to the next permission object: {readMessages: true, sendMessages: true}
. The readMessages: true
permission tells us that the user is allowed to read messages. There is also a sendMessages
property, but we ignore this, since we have already determined that the user is not permitted to send messages.
We look at the final permission object: {readMessages: false, sendMessages: false}
. There are two properties here, but these have both already been determined earlier, so we ignore them. Since we have gone through all permission objects applied to the user, we come to the conclusion that the user may read but not send messages.
The actual priority of permission objects is determined according to the roles applied to the user and channel-specific permissions (which are dependent on the roles), and the order is determined as follows:
- Channel-specific permissions for roles of the user (First.)
- Channel-specific permissions for the
_user
role, if the user is a logged-in member of the server - Channel-specific permissions for the
_everyone
role - Server-wide permissions for roles of the user
- Server-wide permissions for the
_user
role (if applicable, as above) - Server-wide permissions for the
_everyone
role (Last.)
Permissions for roles of the user (both globally and channel-specific) are prioritized according to the role prioritization order. Note that the order of the user's roles
property does not have any effect on the order roles that are applied when calculating their perissions.
A set of permissions can be configured for different roles. When these roles are attached to users, they grant or revoke specific privileges within the entire server.
Below is a table of all permissions.
Name | Description |
---|---|
manageServer |
Allows changes to server settings. |
manageUsers |
Allows for updating of users other than yourself, and allows deletion of users. |
manageRoles |
Allows creation/deletion/modification of roles under you. |
grantRoles |
Allows granting/revoking roles under you to users. |
manageChannels |
Allows management and editing of channels and their permissions. |
managePins |
Allows for pinning and unpinning of messages. |
manageEmotes |
Allows for creation and removal of emotes. |
readMessages |
Allows for viewing of channel messages; if false, the channel does not show up in the channel list. |
sendMessages |
Allows for sending messages. |
deleteMessages |
Allows for deleting messages that you did not author. |
sendSystemMessages |
Allows for sending system messages. |
uploadImages |
Allows image uploads. |
allowNonUnique |
Allows the creation of things with non-unique names. |
Only the following permissions are applicable as channel-specific permission overrides:
Name | Change in meaning |
---|---|
manageChannels |
Allows changes to the role permission overrides of this channel |
readMessages |
If false , the channel will not appear in the channel list for you |
sendMessages |
|
deleteMessages |
|
sendSystemMessages |
Returns { decentVersion, implementation, useSecureProtocol }
, where decentVersion
is a string version number corresponding to the specification version the server supports/providers, implementation
is a string typically refering to the name of the server impementation, and the boolean useSecureProtocol
should be true
when this server is only accessible via the HTTPS and WSS protocols.
Should be used to check to see if a particular server is compatible with the version of the spec that you (the client) support. Note that Decent follows SemVer, so unless the MAJOR (first) portion of the version number is different to what you expect communication should work fine.
GET /api/
<- {
<- "implementation": "@decent/server",
<- "decentVersion": "1.0.0",
<- "useSecureProtocol": true
<- }
- requires permission:
uploadImages
- expects form data (
multipart/form-data
)image
(gif/jpeg/png) - The image to upload. Max size: 10MB
Returns { path }
, where path
is a relative URL to the uploaded image file.
POST /api/upload-image
-> (form data)
<- {
<- "path": "/uploads/1234/image.png"
<- }
This endpoint may return an error, namely FAILED, NO, or NOT_ALLOWED.
{
"name": string,
"iconURL": string,
}
Emitted with data { settings }
when the server settings are modified.
Returns { settings }
, where settings
is an object representing server-specific settings.
GET /api/settings
<- {
<- "settings": {
<- "name": "Unnamed Decent chat server",
<- "iconURL": "https://meta.decent.chat/uploads/..."
<- }
<- }
- requires permission:
manageServer
name
(string; optional)iconURL
(string; optional)
Returns {}
if successful. Updates settings with new values provided, and emits server-settings/update.
PATCH /api/settings
-> {
-> "name": "My Server"
-> }
<- {}
{
"shortcode": string, // Unique string without colons or spaces
"imageURL": string
}
Sent to all clients when an emote is created. Passed data is in the format { emote }
.
Sent to all clients when an emote is deleted. Passed data is in the format { shortcode }
.
Returns { emotes }
, where emotes
is an array of emote objects.
GET /api/emotes
<- {
<- "emotes": []
<- }
- requires permission:
manageEmotes
imageURL
(string)shortcode
(string) - Should not include colons (:
) or spaces. Must be unique, even if the user has theallowNonUnique
permission.
Returns {}
if successful. Emits emote/new.
POST /api/emotes
-> {
-> "imageURL": "https://example.com/path/to/emote.png",
-> "shortcode": "package"
-> }
<- {}
- in-url shortcode (string)
302 redirects to the imageURL
of the emote specified. 404s if not found or invalid.
<!-- To view the :package: emoji in HTML: -->
<img src='/api/emotes/package' width='16' height='16'/>
- requires permission:
manageEmotes
- in-url shortcode (string)
Returns {}
if successful. Emits emote/delete.
DELETE /api/emotes/package
<- {}
{
"id": string,
"dateCreated": float // Unix time at creation. May be more accurate using decimal places
}
- requires a valid session ID & user
Responds with { sessions }
, where sessions
is an array of sessions that also represent the user that the provided session represents (the callee; you).
GET /api/sessions
<- {
<- "sessions": [
<- {
<- "id": "12345678-ABCDEFGH",
<- "dateCreated": 123456789000
<- }
<- ]
<- }
username
(string)password
(string)
Responds with { sessionID }
if successful, where sessionID
is the ID of the newly-created session. Related endpoint: register.
POST /api/sessions
-> {
-> "username": "admin",
-> "password": "abcdef"
-> }
<- {
<- "sessionID": "12345678-ABCDEFGH"
<- }
- does not require a session ID via means other than in the URL
- in-url id (string, session ID)
Responds with { session, user }
upon success, where session
is a session and user
is the user this session represents.
GET /api/sessions/12345678-ABCDEFGH
<- {
<- "session": {
<- "id": "12345678-ABCDEFGH",
<- "dateCreated": 123456789000
<- },
<- "user": {
<- "id": "1234",
<- "username": "admin",
<- // ...
<- }
<- }
- does not require a session ID via means other than in the URL
- in-url id (string, session ID)
Responds with {}
upon success. Any further requests using the provided session ID will fail.
DELETE /api/sessions/12345678-ABCDEFGH
<- {}
{
"id": ID,
"channelID": ID,
// The message type. See below
"type": string,
// The content of the message
"text": string,
// The author's details, at the time of creation;
// if message.type = "system" these will all be null.
"authorID": ID,
"authorUsername": Name,
"authorAvatarURL": string,
// Dates are returned as the number of seconds since UTC 1970-1-1, commonly
// known as Unix time. May be more accurate using decimal places.
"dateCreated": float,
"dateEdited": float | null,
"pinned": boolean,
"mentionedUserIDs": [ ID ]
}
There are currently two message types, "user"
and "system"
. Messages sent by users are always marked "user"
, however both the server and users with the sendSystemMessage
permission can choose to send system-level messages for things, such as user joins or when pins are added. Ideally, these would be styled differently in clients.
System messages lack author
fields.
Mentions target a single user only and are formatted as <@userID>
, where userID
is the ID of the user who is being mentioned. Mentions are stored per-user on the server. mentionedUserIDs
is derived from the content of the message.
Sent to all clients whenever a message is sent to any channel in the server. Passed data is in the format { message }
, where message
is a message representing the new message.
Sent to all clients when any message is edited. Passed data is in the format { message }
, where message
is a message representing the new message.
Sent to all clients when any message is deleted. Passed data is in the format { messageID }
.
- requires permissions:
sendMessages
sendSystemMessages
, iftype == "system"
channelID
(ID) - The parent channel of the new messagetext
(string) - The content of the messagetype
(string; defaults to"user"
)
On success, emits message/new and returns { messageID }
. Also marks channelID
as read for the author. Emits user/mentions/add to mentioned users, if any.
POST /api/messages
-> {
-> "channelID": "5678",
-> "text": "Hello, world!"
-> }
<- {
<- "messageID": "1234"
<- }
- requires permission:
readMessages
- in-url id (ID) - The ID of the message to retrieve
Returns { message }
where message
is a message object.
GET /api/messages/1234
<- {
<- "message": {
<- "id": "1234",
<- // ...
<- }
<- }
- requires a session ID where the session user is the author of message
id
- in-url id (ID) - The ID of the message to edit
text
(string) - The new content of the message
Emits message/edit and returns {}
.
PATCH /api/messages/1234
-> {
-> "text": "Updated message text"
-> }
<- {}
This endpoint will return a NOT_YOURS error if you do not own the message in question. Emits user/mentions/add to newly mentioned users and user/mentions/remove to users who are no longer mentioned, if any.
- requires one of:
- session with ownership of message
id
- permission (for channel of specified message)
deleteMessages
- session with ownership of message
- in-url id (ID) - The ID of the message to delete
Emits message/delete and returns {}
.
DELETE /api/messages/1234
<- {}
This endpoint may return a NOT_YOURS error if you do not own the message in question. Note that admins may delete any message. Emits user/mentions/remove to all previously-mentioned users.
{
"id": ID,
"name": string // Does not include a hash
}
This data is only present if a valid, logged-in session ID is provided to channel-returning endpoints.
{
// Number of 'unread' messages, capped at 200. Unread messages are
// simply messages that were sent more recently than the last time
// the channel was marked read by this user.
"unreadMessageCount": number,
"oldestUnreadMessageID": ID | null,
}
Sent to all clients when a channel is created. Passed data is in the format { channel }
, where channel
is a channel representing the new channel.
Sent to all clients when a channel is updated (renamed, marked as read, etc). Passed data is in the format { channel }
, including channel.unreadMessageCount
if the socket is actively ponging sessionIDs.
Sent to all clients when a message is pinned to a channel. Passed data is in the format { message }
, where message
is the message that was pinned.
Sent to all clients when a message is unpinned from a channel. Passed data is in the format { messageID }
, where messageID
is the ID of the message that was unpinned.
Sent to all clients when a channel is deleted. Passed data is in the format { channelID }
.
- does not require session, however:
- channels where the session user does not have the
readMessages
permission will not be returned - returns extra data with session
- channels where the session user does not have the
Returns { channels }
, where channels is an array of channels. Note unreadMessageCount
will only be returned if this endpoint receives a session.
GET /api/channels
<- {
<- "channels": [
<- {
<- "id": "5678",
<- "name": "general"
<- }
<- ]
<- }
- requires permission
manageChannels
name
(name) - The name of the channel.
On success, emits channel/new and returns { channelID }
.
POST /api/channels
-> {
-> "name": "general"
-> }
<- {
<- "channelID": "5678"
<- }
- does not require session, however:
- returns extra data with session
- in-url id (ID) - The ID of the channel.
Returns { channel }
. Note extra data will only be returned if this endpoint receives a logged-in session ID.
GET /api/channels/5678
<- {
<- "channel": {
<- "id": "5678",
<- "name": "general"
<- }
<- }
- requires permission
manageChannels
- in-url id (ID) - The ID of the channel.
- name (name) - The new name of the channel
Returns {}
if successful, emitting channel/update.
PATCH /api/channels/5678
-> {
-> "name": "best-channel"
-> }
<- {}
- requires permission
manageChannels
- in-url id (ID) - The ID of the channel to delete.
Returns {}
if successful. Emits channel/delete.
DELETE /api/channels/5678
<- {}
- requires permission (for specified channel)
readMessages
- in-url id (ID) - The ID of the channel.
Marks the channel as read (ie. sets unreadMessageCount
to 0), returning {}
. Emits channel/update including extra data if this socket is authenticated.
POST /api/channels/5678/mark-read
<- {}
- requires permission (for specified channel)
readMessages
- in-url id (ID) - The ID of the channel to fetch messages of.
before
(ID; optional) - The ID of the message right after the range of messages you want.after
(ID; optional) - The ID of the message right before the range of messages you want.limit
(integer; optional, default50
) - The maximum number of messages to fetch. Must be1 <= limit <= 50
.
Returns { messages }
, where messages is an array of the most recent messages sent to this channel. If limit
is given, it'll only fetch that many messages.
If before
is specified, it'll only return messages sent before that one; and it'll only return messages sent after after
.
GET /api/channels/5678/messages
<- {
<- "messages": [
<- {
<- "id": "1234",
<- "channelID": "5678",
<- // ...
<- },
<- {
<- "id": "1235",
<- "channelID": "5678",
<- // ...
<- }
<- ]
<- }
GET /api/channels/5678/messages?after=1234
<- {
<- "messages": [
<- {
<- "id": "1235",
<- "channelID": "5678",
<- // ...
<- }
<- ]
<- }
- requires permission (for specified channel)
manageChannels
- in-url id (ID)
- rolePermissions - an object map of role IDs to their permissions, limited by channel-specific applicable permissions only
- The internal role
_everyone
cannot override permissions other thanreadMessages
, as you must be logged in to perform any other action.
- The internal role
Returns {}
if successful. Note that if a role is not specified on the roles parameter, its permissions on the channel will not be changed. To delete an entry, pass {}
as the role's permissions; since this would reset the role's permissions all to unset, the role would have no effect, and is removed from the channel's rolePermissions
map.
PATCH /api/channels/1234/role-permissions
-> {
-> "rolePermissions": {
-> "_everyone": {
-> "readMessages": false,
-> "sendMessages": false
-> },
-> "123": {
-> "readMessages": true,
-> "sendMessages": true
-> }
-> }
-> }
<- {}
- in-url id (ID)
Returns { rolePermissions }
if successful, where rolePermissions
is a map of role IDs to their individual permissions.
GET /api/channels/1234/role-permissions
<- {
<- "rolePermissions": {
<- "_everyone": {
<- "readMessages": false,
<- "sendMessages": false
<- },
<- ...
<- }
<- }
- requires permission (for specified channel)
readMessages
- in-url id (ID)
Returns { pins }
, where pins is an array of messages that have been pinned to this channel.
GET /api/channels/5678/pins
<- {
<- "pins": [
<- {
<- "id": "1235",
<- "channelID": "5678",
<- // ...
<- }
<- ]
<- }
- requires permission (for specified channel)
managePins
- in-url id (ID)
messageID
(ID) - The message to pin to this channel.
Returns {}
if successful. Emits channel/pins/add.
POST /api/channels/5678/pins
-> {
-> "messageID": "1234"
-> }
<- {}
- requires permission (for specified channel)
managePins
- in-url channelID (ID)
- in-url messageID (ID) - The ID of the message to unpin. Errors if not pinned.
Returns {}
if successful. Emits channel/pins/remove.
DELETE /api/channels/5678/pins/1234
<- {}
{
"id": ID,
"username": Name,
"avatarURL": string,
"flair": string | null,
"online": boolean,
"roleIDs": array, // Array of string IDs for each role the user has, not including "_user" or "_everyone",
"email": string | null // Only provided if the requested user is the same as the sessionID provides
}
Sent to all clients when a user is created. Passed data is in the format { user }
.
Sent to all clients when a user is deleted. Passed data is in the format { userID }
.
Sent to all clients when a user becomes online. This is whenever a socket tells the server that its session ID is that of a user who was not already online before. Passed data is in the format { userID }
.
Sent to all clients when a user becomes offline. This is whenever the last socket of a user who is online terminates. Passed data is in the format { userID }
.
Sent to all clients when a user is mutated using PATCH /api/users/:userID. Passed data is in the format { user }
.
When a user is mentioned, this is sent to all sockets authenticated as them. Passed data is in the format { message }
, where message
is the new / just edited mesage that mentioned the user.
When a message is deleted or edited to remove the mention of a user, all sockets authenticated as the unmentioned user are sent this event. Passed data is in the format { messageID }
, where messageID
is the ID of the message that just stopped mentioning the user.
Returns { users }
, where users
is an array of users.
GET /api/users
<- {
<- "users": [
<- {
<- "id": "1234",
<- "username": "test-user",
<- // ...
<- }
<- ]
<- }
GET /api/users?sessionID=adminsid123
<- {
<- "users": [
<- {
<- "id": "1234",
<- "username": "test-user",
<- // ...
<- }
<- ]
<- }
username
(name) - Must be uniquepassword
(string) - Errors if shorter than 6 characters
Responds with { user }
if successful, where user
is the new user object. Emits user/new. Log in with POST /api/sessions.
POST /api/users
-> {
-> "username": "joe",
-> "password": "secret"
-> }
<- {
<- "user": {
<- "id": "8769",
<- "username": "joe",
<- // ...
<- }
<- }
- does not require a valid session, howerver:
- returns extra data (
email
) if the provided session represents the user requested
- returns extra data (
- in-url id (ID) - The user ID to fetch
Returns { user }
.
GET /api/users/1
<- {
<- "user": {
<- "id": "1",
<- "username": "admin",
<- // ...
<- }
<- }
- does not require session, however:
- only returns messages where you have the
viewMessages
permission for the message's channel
- only returns messages where you have the
- in-url id (ID) - The user ID to fetch the mentions of
limit
(int <= 50; default50
) - The maximum number of mentions to fetch.skip
(int; default0
) - Skips the first n mentions before returning
Returns { mentions }
, where mentions
is an array of messages. Note that mentions are sorted by creation date: mentions[0]
is the most recent mention.
Combining limit
and skip
can net you simple pagination.
GET /api/users/1/mentions?limit=1
<- {
<- "mentions": [
<- {
<- "text": "Hey <@1>! How are you?"
<- // ...
<- },
<-
<- // ...
<- ]
<- }
- requires valid, logged-in session (see below)
- in-url id (ID) - The user ID to patch
The following parameters are available to sessions that represent the user being updated:
password
(object; optional):new
(string) - Errors if shorter than 6 charactersold
(string) - Errors if it doesn't match user's existing password
The following parameters are available to sessions that represent the user being updated, or have the manageUsers
permission:
email
(string | null; optional) - Not public, used to generate avatar URLflair
(string | null; optional) - Displayed beside username in chat, errors if longer than 50 characters
Returns {}
and applies changes, assuming a valid session for this user (or an admin) is provided and no errors occur. Also emits user/update.
PATCH /api/users/1
(with session representing user id 1)
-> {
-> "password": {
-> "old": "abcdef",
-> "new": "secure"
-> }
-> }
<- {}
PATCH /api/users/12
(with session representing an admin)
-> {
-> "roleIDs": [ "id-of-role", "id-of-role-2" ],
-> "flair": null
-> }
<- {}
('flair: null' removes the flair.)
- requires permission:
grantRoles
- also require more permissions (see below)
- in-url userID (ID) - The ID of the user to give the role to
- roleID (ID) - The ID of the role to be given
The role may only be given if the requesting user has all the permissions that are specified by that role (even if the value specified by the role is false).
On success, emits user/update and returns {}
.
- requires permission:
grantRoles
- also requires more permissions (see below)
- in-url userID (ID) - The ID of the user to take the role from
- in-url roleID (ID) - The ID of the role to be taken
As with giving a role, the role may only be taken if the requesting user has all the permissions that are specified by that role (even if the value specified by the role is false).
On success, emits user/update and returns {}
.
- does not require a session
- in-url id (ID) - The ID of the user to fetch the roles of
Returns { roleIDs }
. (Not actually more functionally useful than simply checking user.roleIDs
from /api/users/:id
; only exists for convenience.)
- does not require a session, however:
- if the provided session represents the user
id
, returns extra data (email
)
- if the provided session represents the user
- in-url id (ID) - The user ID to fetch
Returns { user }
.
GET /api/users/1
<- {
<- "user": {
<- "id": "1",
<- "username": "admin",
<- // ...
<- }
<- }
- in-url id (ID) - The user ID to fetch
Returns { permissions }
, where permissions
is a permissions object.
GET /api/users/1/permissions
<- {
<- "permissions": {
<- "manageServer": false,
<- "manageUsers": false,
<- "readMessages": true,
<- // ...
<- }
<- }
- in-url userID (ID) - The user ID to fetch
- in-url channelID (ID) - The channel ID to fetch
Returns { permissions }
, where permissions
is a permissions object containing permissions, with the given channel's role-specific permissions applied.
- requires permission:
manageUsers
- in-url id (ID) - The user to delete
Returns {}
and emits user/delete.
- does not require session
- in-url username (name)
On success, returns { available }
, where available is a boolean for if the username is available or not. May return the error INVALID_NAME.
GET /api/username-available/patrick
<- {
<- "available": false
<- }
{
"id": ID,
"name": string,
"permissions": object, // A permissions object
}
- Permissions
- (Spec) Internal roles
Sent to all clients when a role is added. Passed data is in the format { role }
.
Sent to all clients when a role is updated. Passed data is in the format { role }
.
Sent to all clients when a role is deleted. Passed data is in the format { roleID }
.
Returns { roles }
, where roles
is an array of role objects.
GET /api/roles
<- {
<- "roles": [
<- {
<- "id": "_everyone",
<- "name": "Everyone",
<- "permissions": ...
<- }
<- ]
<- }
Returns { roleIDs }
, where roleIDs
is an array of role IDs representing the order that roles are applied when permissions are calculated. Internal roles, such as _user
and _everyone
, are not included.
- requires permission:
manageRoles
roleIDs
(array of IDs) - The order roles are applied in- Must contain all non-internal role IDs exactly once (no more, no less)
- The requesting user can reorder all roles which are already prioritized below their own most-prioritized role; the order of said role and all roles above must not be changed
- The order cannot be changed such that the requesting user would not have the
manageRoles
permission anymore
Returns {}
when successful. Changes the order that roles are applied in; initial items are the most prioritized. See Permissions.
PATCH /api/roles/order
-> {
-> "roleIDs": [
-> "abc",
-> "123",
-> "999"
-> ]
-> }
// Then...
GET /api/roles
<- {
<- "roles": [
<- {"id": "abc", ...},
<- {"id": "123", ...},
<- {"id": "999", ...},
<- {"id": "_user", ...},
<- ...
<- ]
<- }
Returns { role }
.
GET /api/roles/_everyone
<- {
<- "role": {
<- "id": "_everyone",
<- "name": "Everyone",
<- "permissions": ...
<- }
<- }
- requires permission:
manageRoles
name
(string) - Max length 32.permissions
(Permissions object) - this role's intended permissions- Cannot contain permissions that the requesting session's user does not have
Returns { roleID }
if successful, where roleID
is the ID of the new role. Emits role/new. The role is added to the role prioritization order immediately under (less prioritized than) the creating user's most-prioritized role.
- requires permission:
manageRoles
- in-url id (ID)
- must not refer to an internal role
name
(string; optional) - Max length 32.permissions
(Permissions object) - the new intended permissions for this role- Cannot contain permissions that the requesting session's user does not have
Returns {}
and emits role/update if successful. May emit user/update as required if users' computed permissions change.
- requires permission:
manageRoles
- in-url id (ID string)
- must not refer to an internal role
Returns {}
if successful. Emits role/delete. The role is removed from the role prioritization order.