Skip to content
Fluxer API

Messages

A message is one post in a channel, together with the text, attachments, embeds, stickers, and reactions stored with it. Channel metadata and membership are defined by the Channels resource.

Two terms recur below. A text-bearing channel is a channel type that stores messages, which is every type except a guild category and a guild link channel. The message history cutoff is an instant a guild stores on itself, and a member without READ_MESSAGE_HISTORY reads nothing created before it.

Fluxer resolves the channel before it applies any per-route authorisation. A private channel returns 404 UNKNOWN_CHANNEL to a caller who is not a recipient. A guild channel returns 403 MISSING_PERMISSIONS to a non-member and to a member without VIEW_CHANNEL. A guild an operator has marked unavailable returns 403 MISSING_ACCESS before the route runs, and a guild that no Gateway process serves returns 404 UNKNOWN_GUILD, or 403 ACCESS_DENIED when its stored record survives.

The message read, create, modify, and delete routes, Bulk delete messages, Bulk delete own messages, and List pinned messages also enforce age verification on an effectively age restricted guild channel. They return 403 NSFW_CONTENT_AGE_RESTRICTED until the account satisfies it. The attachment routes, the pin routes, the reaction routes, and Indicate typing resolve the channel without that check.

Clear channel read state and Acknowledge message resolve no channel. Acknowledge pins reads the channel without checking the caller’s access. None of the three evaluates a permission.

A message object is the full stored form of one post in a channel.

FieldTypeDescription
idsnowflakeThe ID of the message
channel_idsnowflakeThe ID of the channel
author1partial user objectThe user credited with the message
webhook_id?snowflakeOriginating webhook ID, present only for a webhook-authored message
typeintegerMessage type
flagsintegerMessage flags
contentstringThe text of the message, empty when the message has only media
timestampISO8601 timestampCreation time derived from the message snowflake
edited_timestamp?ISO8601 timestampMost recent edit time, or null when the message has never been edited
pinnedbooleanWhether the message is pinned
mention_everyonebooleanWhether the message mentions everyone
tts2booleanWhether the message requested text-to-speech presentation
mentions3array[partial user object]The users the message actively mentions
mention_rolesarray[snowflake]The IDs of the roles the message actively mentions
mention_channels?array[channel mention object]The channels the message content links by ID
users?3array[partial user object]Users referenced by non-notifying content, embed, and snapshot text
embeds4array[embed object]The previews resolved or supplied for the message
attachments5array[message attachment object]The files attached to the message
stickersarray[sticker item object]The stickers sent with the message
nsfw_emojis?array[snowflake]IDs of the custom emojis in the message that are classified as explicit
reactions?array[reaction object]Ordinary reaction summaries
message_reference?message reference objectReply or forward reference
message_snapshots?array[message snapshot object]The immutable copies captured for a forward
nonce?6stringCaller-supplied message nonce, echoed to the sender as a string of 1 through 32 characters
call?message call objectCall state attached to a call message
referenced_message?7?message objectResolved referenced message without a nested referenced_message field

1 Synthesised for a webhook-authored message and for a stored author ID that no longer resolves

2 Echoed from the create request, so a message read through any other operation always reports false

3 A user who became an active mention appears in mentions, and a user who is only referenced by rendered text appears in users instead, so the two arrays never contain the same user

4 Empty while SUPPRESS_EMBEDS is set on the message

5 An attachment that a resolved embed owns is excluded from this array and is exposed through that embed’s media object instead

6 Echoed only in the create message response and its originating Message Create Gateway Dispatch, and never stored on the message

7 The key is absent when the message has no reply reference, present and null when the reply target no longer resolves, and present with the message when it does. A client must tell absent apart from null by key presence

A webhook-authored message has no stored author user. Fluxer builds its author from the webhook, with the webhook ID as id, the stored webhook name as username, the discriminator 0000, the stored webhook avatar hash as avatar, and bot true. A message whose stored author ID no longer resolves to an account is served with a deleted-user placeholder. The placeholder has that ID, the discriminator 0000, and no avatar.

mentions, mention_roles, embeds, attachments, and stickers are always present and can be empty. Every optional field above is omitted entirely, with referenced_message as the one exception. A message whose author user and webhook are both absent is omitted from every read.

{
"id": "1501320000000000000",
"channel_id": "1501314428688998182",
"author": {
"id": "1501314428688990000",
"username": "ada",
"discriminator": "0001",
"avatar": "a1b2c3d4e5f60718293a4b5c6d7e8f90"
},
"type": 0,
"flags": 0,
"content": "shipping it",
"timestamp": "2026-08-31T09:14:02.000Z",
"edited_timestamp": null,
"pinned": false,
"mention_everyone": false,
"tts": false,
"mentions": [],
"mention_roles": [],
"embeds": [],
"attachments": [],
"stickers": []
}
ValueNameDescription
0DEFAULT1 2Ordinary message
1RECIPIENT_ADDGroup direct message recipient-add system message
2RECIPIENT_REMOVEGroup direct message recipient-remove system message
3CALLPrivate call system message
4CHANNEL_NAME_CHANGEGroup direct message name-change system message
5CHANNEL_ICON_CHANGEGroup direct message icon-change system message
6CHANNEL_PINNED_MESSAGE2Channel pin system message
7USER_JOIN2User-join system message
19REPLY1 2Message with a reply reference

1 Only this type can be modified, pinned, unpinned, or used as the target of a reply reference. Any other type rejects modification, pinning, and unpinning with 400 CANNOT_MODIFY_SYSTEM_WEBHOOK, and rejects being replied to with 400 CANNOT_REPLY_TO_SYSTEM_MESSAGE

2 Only this type can be deleted, and any other type rejects deletion with 403 MISSING_PERMISSIONS

ValueNameDescription
1 << 2SUPPRESS_EMBEDS1Suppress rendering of embeds
1 << 12SUPPRESS_NOTIFICATIONSDo not generate ordinary mention notifications
1 << 13VOICE_MESSAGE2Message has one voice recording attachment

1 The only flag a guild moderator can change on a message they did not author

2 Setting this flag binds the message to the voice message contract described under Create message

These three bits are also the complete sendable set. A create masks the supplied value down to them, and a modify replaces only them and leaves every other stored bit untouched. A bit outside this table is discarded, and the request still succeeds.

An attachment is one file stored against a message and served from media delivery.

FieldTypeDescription
idsnowflakeThe ID of the attachment
filenamestringThe filename stored with the attachment
title?stringDisplay title, or null when none is stored
description?stringAlternative text or description, or null when none is stored
content_type1stringThe media type detected for the attachment
content_hash?stringThe hash of the attachment’s stored bytes, or null when they were never hashed
sizeintegerThe stored size of the attachment in bytes
url2?stringPublic attachment URL, or null once the attachment has expired
proxy_url2?stringMedia Proxy URL, or null once the attachment has expired
width?3integerPixel width for visual media
height?3integerPixel height for visual media
placeholder?stringEncoded media placeholder
flagsintegerAttachment flags
nsfw?booleanWhether media inspection marked the attachment explicit
duration?integerAudio or video duration in seconds
waveform?stringBase64-encoded voice waveform
expires_at4?ISO8601 timestampAttachment URL expiry time, or null when the attachment has no recorded decay deadline
expired?5booleanWhether the attachment is expired

1 Always present. It falls back to a type guessed from the stored filename when the attachment has no recorded media type, and to application/octet-stream when the filename yields no guess

2 Both fields are the same canonical media endpoint URL, and both become null together once the attachment has expired

3 Omitted for an audio media type even when a stored dimension exists

4 The key is always present. Its value is the recorded decay deadline, or null when the attachment has none

5 Present and true only when the attachment has already expired, so an absent key must be read as false

{
"id": "1501320000000000001",
"filename": "diagram.png",
"title": null,
"description": "Sequence diagram",
"content_type": "image/png",
"content_hash": "9f86d081884c7d659a2feaa0c55ad015",
"size": 18422,
"url": "https://media.example.com/attachments/1501314428688998182/1501320000000000001/diagram.png",
"proxy_url": "https://media.example.com/attachments/1501314428688998182/1501320000000000001/diagram.png",
"width": 1280,
"height": 720,
"flags": 0,
"expires_at": null
}
ValueNameDescription
1 << 3IS_SPOILERAttachment is presented as a spoiler
1 << 4CONTAINS_EXPLICIT_MEDIAAttachment contains explicit media
1 << 5IS_ANIMATEDAttachment is animated

An emoji is either a custom guild emoji identified by ID or a standard Unicode emoji.

FieldTypeDescription
id?snowflakeThe ID of the custom emoji, absent for a Unicode emoji
name1stringEmoji name or Unicode value
animated?booleanWhether a custom emoji is animated

1 Holds the guild emoji name for a custom emoji and the literal Unicode sequence for a standard emoji

A reaction object summarises one emoji group on a message. Fluxer has ordinary reactions only.

FieldTypeDescription
emojiemoji objectThe emoji this group counts
count1integerThe number of users who added this emoji
me?2booleanWhether the authenticated user has this reaction

1 Capped by the resolved max_users_per_message_reaction limit, which defaults to 1,000,000 users for each group

2 Present and true only when the authenticated user has this reaction, and omitted entirely otherwise, so an absent key must be read as false

A message has at most the resolved max_reactions_per_message distinct groups, which defaults to 30. Groups are ordered by the time each group’s earliest reaction was added, then by emoji name, then by emoji ID.

{
"emoji": {
"id": "1501314428688991234",
"name": "party_parrot",
"animated": true
},
"count": 7,
"me": true
}

A message reference names the message that a reply points at or that a forward was taken from.

FieldTypeDescription
channel_idsnowflakeThe ID of the referenced channel
message_idsnowflakeThe ID of the referenced message
guild_id?snowflakeThe ID of the referenced guild, present only for a guild message
typeintegerMessage reference type
ValueNameDescription
0DEFAULT1Reply reference
1FORWARD2Forward reference represented by snapshots

1 The default when a create message request supplies message_reference without a type

2 Requires channel_id in the create message request, and the created message has message_snapshots and no referenced_message

A message reference input names the source message a create request replies to or forwards.

FieldTypeDescription
message_idsnowflakeThe ID of the referenced message
channel_id?1snowflakeThe ID of the referenced channel, required for a forward reference
guild_id?snowflakeThe ID of the referenced guild when applicable
type?integerMessage reference type, defaulting to DEFAULT
attachment_ids?2array[snowflake]At most 10 selected attachment IDs for a forward
embed_indices?2array[integer]At most 10 non-negative selected embed indices for a forward

1 A FORWARD reference without it fails validation, and a reply reference defaults to the channel the new message is being sent to

2 Selects a subset of the source message’s media to snapshot, and omitting both snapshots everything the source message has

A snapshot is the flat immutable copy of one forwarded message. It has no message ID, channel ID, or author, so a client cannot trace a forward back to its source through this object.

FieldTypeDescription
content?stringSnapshotted text
timestampISO8601 timestampOriginal creation time
edited_timestamp?ISO8601 timestampOriginal edit time, omitted when the original message was never edited
mentions?1array[snowflake]Snapshotted mentioned user IDs
mention_roles?array[snowflake]Snapshotted mentioned role IDs
mention_channels?array[channel mention object]Snapshotted mentioned channels
embeds?array[embed object]Snapshotted embeds
attachments?2array[message attachment object]Snapshotted attachments
stickers?array[sticker item object]Snapshotted stickers
typeintegerOriginal message type
flagsintegerOriginal message flags

1 A client resolves each snapshotted ID against the enclosing message’s users array

2 Snapshot attachments are independent stored objects, so deleting the source message leaves them intact

Every optional field above is omitted entirely.

A message call has the participants and end time of the call that a CALL message records.

FieldTypeDescription
participantsarray[snowflake]Current participant user IDs
ended_timestamp?ISO8601 timestampCall end time, or null while the call is still active

A channel mention names one channel that the message content links by ID.

FieldTypeDescription
idsnowflakeThe ID of the mentioned channel
namestringMentioned channel name
typeintegerChannel type

A sticker item is the trimmed sticker record on a message.

FieldTypeDescription
idsnowflakeThe ID of the sticker
namestringSticker name
animatedbooleanWhether the sticker is animated
nsfw?booleanWhether the sticker is classified as explicit

An embed is a rendered preview on a message, either resolved by the unfurler or supplied as rich input.

FieldTypeDescription
typestringEmbed type
title?stringEmbed title
description?stringEmbed description
url?stringEmbed destination URL
timestamp?ISO8601 timestampEmbed timestamp
color?integerEmbed colour
author?embed author objectEmbed author
provider?1embed provider objectExternal provider
thumbnail?embed media objectThumbnail image
image?embed media objectMain image
video?1embed media objectVideo media
audio?1embed media objectAudio media
footer?embed footer objectEmbed footer
fields?array[embed field object]Embed fields
nsfw?booleanWhether the embed contains explicit media
html?1stringSanitised oEmbed markup for a trusted specialised renderer
html_width?1integerPreferred pixel width of the sanitised oEmbed markup
html_height?1integerPreferred pixel height of the sanitised oEmbed markup
children?1array[embed object]At most one nested unfurler-generated embed, which itself has no children field

1 Produced only by the unfurler when it resolves a link, and never accepted from a rich embed input

Every optional field above is omitted entirely.

{
"type": "rich",
"title": "Release 2.4.0",
"description": "Voice reconnects are now instant.",
"url": "https://example.com/releases/2.4.0",
"color": 5793266,
"footer": {"text": "example.com"},
"fields": [{"name": "Platform", "value": "Desktop", "inline": true}]
}
ValueDescription
richAn embed the unfurler assembled itself, and the type of every accepted rich embed input
linkA generic link preview with page metadata and no resolved media
imageAn image preview resolved from a linked URL
videoA video preview resolved from a linked URL
audioAn audio preview resolved from a linked URL
gifvAn animated looping video preview
articleAn article or encyclopaedia page preview
blueskyA Bluesky post preview
FieldTypeDescription
namestringAuthor name
url?stringAuthor link
icon_url?stringAuthor icon URL
proxy_icon_url?stringProxied author icon URL
FieldTypeDescription
urlstringMedia URL
proxy_url1stringMedia Proxy URL
width?integerPixel width
height?integerPixel height
duration?integerDuration in seconds
description?stringMedia description
content_type?stringMedia type
content_hash?stringContent hash
placeholder?stringEncoded media placeholder
flags?integerMedia flags using CONTAINS_EXPLICIT_MEDIA and IS_ANIMATED from attachment flags

1 Always derived from url, so every serialised media object has it

FieldTypeDescription
textstringFooter text
icon_url?stringFooter icon URL
proxy_icon_url?stringProxied footer icon URL
FieldTypeDescription
namestringField name
valuestringField value
inlinebooleanWhether the field can render inline

Fluxer populates a provider only from resolved embed metadata.

FieldTypeDescription
namestringProvider name
url?stringProvider URL

An allowed mentions object decides which mentions written in the message text become active mentions, meaning the ones that notify a user or role. Omitting the object lets every mention in the text become active, subject to the caller’s permissions.

FieldTypeDescription
parse?1 2array[string]Mention categories from allowed mention parse values
users?2array[snowflake]At most 100 user IDs permitted to become active mentions
roles?2array[snowflake]At most 100 role IDs permitted to become active mentions
replied_user?3booleanWhether a reply mentions the referenced message author (default true)

1 Defaults to every category when the object is absent, to the empty set when users or roles is supplied without it, and to the empty set when the object is present with none of its four fields

2 A non-empty parse combined with a non-empty users or roles is rejected with 400 PARSE_AND_USERS_OR_ROLES_CANNOT_BE_USED_TOGETHER

3 Ignored in a one-to-one direct message and in personal notes, and ignored when the referenced message has the same author as the new message

mention_everyone is forced to false whenever the caller lacks MENTION_EVERYONE, without failing the request.

ValueDescription
usersParse user mentions
rolesParse role mentions
everyoneParse @everyone and @here mentions

A new message can refer to a previously uploaded attachment or attach a direct multipart file. An edited message can retain an existing attachment. Attachment IDs in a direct multipart request identify the matching zero-based files[N] field.

FieldTypeDescription
id1integer | integer stringAttachment position
filenamestringAttachment filename
upload_filename2stringOpaque upload key returned by Request attachment upload URLs
file_size1integerUploaded byte count
content_typestringMedia type of 1 through 255 characters
title??stringDisplay title (1-1,024 characters)
description??stringDescription (1-4,096 characters)
duration?3?integerVoice media duration in seconds (0-2,147,483,647)
waveform?3?stringBase64 waveform of 1 through 4,096 characters
flags?integerAttachment flags, defaulting to 0

1 Accepted either as a JSON number or as a decimal string

2 The presence of this key is the discriminator that selects this variant over the direct multipart metadata variant

3 Both are required when the message has the VOICE_MESSAGE flag. A waveform on an attachment whose resolved media type is not audio/* fails with 400 VOICE_MESSAGES_ATTACHMENT_MUST_BE_AUDIO

Only IS_SPOILER and CONTAINS_EXPLICIT_MEDIA survive from a caller-supplied flags value. IS_ANIMATED is set by media inspection alone.

Direct multipart attachment metadata object

Section titled “Direct multipart attachment metadata object”
FieldTypeDescription
id1integer | integer stringZero-based files[N] index
filenamestringDisplay filename
content_type?stringMedia type of 1 through 255 characters
title??stringDisplay title (1-1,024 characters)
description??stringDescription (1-4,096 characters)
flags?integerAttachment flags, defaulting to 0
duration?2?integerVoice media duration in seconds (0-2,147,483,647)
waveform?2?stringBase64 waveform of 1 through 4,096 characters

1 An entry whose id matches no supplied file index and that has a filename fails with 400 NO_FILE_FOR_ATTACHMENT_METADATA. An entry whose id matches no supplied file and that has no filename is read as an existing attachment reference instead

2 Both are required when the message has the VOICE_MESSAGE flag

Fluxer discards a key outside the table above and accepts the rest of the entry.

FieldTypeDescription
idsnowflake | integerExisting attachment ID or attachment position
title??stringReplacement display title (1-1,024 characters)
description??stringReplacement description (1-4,096 characters)
flags?1integerAttachment flags, accepted and discarded
filename?1 2stringDisplay filename, accepted and discarded
duration?1 2?integerDuration in seconds (0-2,147,483,647), accepted and discarded
waveform?1 2?stringBase64 waveform of 1 through 4,096 characters, accepted and discarded

1 A retained attachment is rebuilt from its stored record, and only title and description are written back onto it

2 Rejected with 400 CANNOT_EDIT_ATTACHMENT_METADATA when the caller is a guild moderator editing a message they did not author, because that caller can supply only id, title, description, and flags

A rich embed input is an embed a client supplies on a message, and Fluxer always stores it with the rich embed type. The number of embeds on one message is bounded by the resolved max_embeds_per_message limit, which defaults to 10, and exceeding it fails with 400 TOO_MANY_EMBEDS.

FieldTypeDescription
url??stringEmbed destination URL (1-2,048 characters)
title??stringTitle with at most 256 characters
color??integerEmbed colour
timestamp??ISO8601 timestampEmbed timestamp
description??stringDescription (1-4,096 characters, empty string treated as absent)
author?1?embed author input objectAuthor metadata
image?1?embed media input objectMain image metadata
thumbnail?1?embed media input objectThumbnail metadata
footer?1?embed footer input objectFooter metadata
fields??array[embed field input object]At most 25 embed fields

1 A nested object that omits its own required field is discarded. An author without name, a media object without url, and a footer without text are read as if the field had not been sent

FieldTypeDescription
namestringAuthor name (1-256 characters)
url??stringAuthor link (1-2,048 characters)
icon_url??stringAuthor icon URL (1-2,048 characters)
FieldTypeDescription
url1stringMedia URL or attachment reference
description??stringMedia description (1-4,096 characters)

1 Either an http or https URL, or an attachment://<filename> reference naming a png, jpg, jpeg, webp, or gif attachment on the same message, and from 1 through 2,048 characters in either form. Only image and thumbnail accept the attachment:// form

An attachment:// reference on a request that has no attachment fails with 400 CANNOT_REFERENCE_ATTACHMENTS_WITHOUT_ATTACHMENTS. A reference to a filename that no attachment on the request supplies fails with 400 REFERENCED_ATTACHMENT_NOT_FOUND, and a reference to an attachment whose extension is not a supported image extension fails with 400 ATTACHMENT_MUST_BE_IMAGE.

FieldTypeDescription
textstringFooter text (1-2,048 characters)
icon_url??stringFooter icon URL (1-2,048 characters)
FieldTypeDescription
namestringField name (1-256 characters)
valuestringField value with at most 1,024 characters
inline?booleanWhether the field can render inline, defaulting to false

Fluxer issues an upload URL for an attachment before any message can reference it. Request attachment upload URLs plans the upload. A plan whose declared size exceeds 10 MiB is a multipart plan, and Complete attachment upload finalises it.

An upload_url is either a presigned object storage URL or a Fluxer upload relay URL, and the instance decides which per request from the caller’s country. A caller whose IP is unknown, or whose country is not on the instance’s direct-upload list, is handed a relay URL. A client MUST send the URL exactly as issued and MUST NOT assume either shape.

Only a message that the same identity creates in the same channel can reference the key an upload plan yields.

One declared upload inside a Request attachment upload URLs body.

FieldTypeDescription
id1integerCaller-selected attachment position (0-2,147,483,647)
filenamestringFilename to upload
file_size1integerDeclared byte count (0-9,007,199,254,740,991)
content_type2stringMedia type of 1 through 255 characters the client uploads

1 A decimal string is coerced to the integer

2 The issued capability and the stored attachment both use the media type derived from filename

Returned when the declared file_size is at most 10 MiB.

FieldTypeDescription
idintegerCaller-selected attachment position echoed from the request
filenamestringFilename echoed from the request
upload_filename1stringOpaque upload key of 1 through 4,096 characters
file_sizeintegerDeclared byte count echoed from the request
content_typestringMedia type derived from filename
upload_modestringAlways singlepart
upload_url2stringPresigned URL that accepts the complete file in one PUT

1 This value is the upload_filename of a pre-uploaded attachment in a later Create message or Modify message request

2 The capability is bound to the derived media type and to exactly file_size bytes, so a PUT of any other length is rejected

Returned when the declared file_size exceeds 10 MiB.

FieldTypeDescription
idintegerCaller-selected attachment position echoed from the request
filenamestringFilename echoed from the request
upload_filenamestringOpaque upload key of 1 through 4,096 characters
file_sizeintegerDeclared byte count echoed from the request
content_typestringMedia type derived from filename
upload_modestringAlways multipart
upload_idstringObject storage multipart upload identifier of 1 through 1,024 characters
part_size1integerByte size of every part except the last
partsarray[attachment upload part object]Presigned part capabilities in ascending part number (1-10,000 entries)

1 The plan targets 20 parts, so part_size is one twentieth of file_size rounded up to a whole mebibyte, and it is never smaller than 10 MiB. The last part is the remainder

One presigned part of a multipart upload plan.

FieldTypeDescription
part_numberintegerOne-based part number
upload_url1stringPresigned URL that accepts exactly this part

1 Each capability is bound to the exact byte count of its part, so a PUT of any other length is rejected

One planned upload named in a Complete attachment upload body.

FieldTypeDescription
upload_filenamestringOpaque upload key returned when the upload was planned
upload_idstringMultipart upload identifier returned when the upload was planned

A channel pin pairs one pinned message with the time it was pinned.

FieldTypeDescription
message1message objectThe message the pin points at
pinned_atISO8601 timestampTime at which the message was pinned

1 The pinned message omits referenced_message and reactions, so a client that needs either must read the message through Get message

FieldTypeDescription
items1array[channel pin object]Current page of pins
has_morebooleanWhether an older page exists

1 Ordered by descending pin time

The page has no cursor field. The next request repeats the operation with before set to the pinned_at of the last returned item. Continue while has_more is true. has_more is false only when the channel has no further visible pins.

FieldTypeDescription
itemsarray[partial user object]Users in ascending cursor order
has_morebooleanWhether another page exists
next_after1?snowflakeUser ID cursor for the next page

1 Null when no further page exists, and otherwise the ID of the last user in items

FieldTypeDescription
channel_idsnowflakeThe ID of the channel
limitintegerNumber of messages to return (1-50)
before?snowflakeReturn messages before this message ID
after?snowflakeReturn messages after this message ID
around?snowflakeReturn a window centred on this message ID
FieldTypeDescription
channel_idsnowflakeThe ID of the channel
messagesarray[message object]Reverse-chronological message window
GET/v1/channels/{channel_id}/messagesBot

Returns a reverse-chronological array of message objects. Requires VIEW_CHANNEL.

  • Reading history in a guild channel requires READ_MESSAGE_HISTORY.
  • A guild caller without READ_MESSAGE_HISTORY sees only messages created on or after the guild’s message history cutoff.
FieldTypeDescription
channel_idsnowflakeThe ID of the channel
FieldTypeDescription
limit?integerNumber of messages to return (1-100, default 50)
before?1snowflakeReturn messages before this message ID
after?1snowflakeReturn messages after this message ID
around?snowflakeReturn a window centred on this message ID, overriding before and after

1 Combining the two selects the page before before, then discards entries at or below after

StatusBodyCondition
200array[message object]Message window was returned
403error responseCaller lacks VIEW_CHANNEL and the request returns MISSING_PERMISSIONS, or the caller lacks age verification for the channel and the request returns NSFW_CONTENT_AGE_RESTRICTED
404error responseChannel does not exist or the caller is not a recipient of the private channel

100 requests per 10 seconds for each authenticated user and channel ID, on the channel:messages:read::channel_id bucket.

POST/v1/channels/messages/bulk

Returns a bulk message response object holding bounded message windows from several channels.

  • This is a user-only operation, and a bot credential is refused with 403 ACCESS_DENIED.
  • Fluxer resolves and authorises each requested channel independently, under exactly the same boundary as List channel messages.
  • An inaccessible channel fails the whole request, so the response has no window for any channel.
FieldTypeDescription
requests1array[bulk message request object]From 1 through 25 channel requests

1 The limit values across all entries must sum to at most 250, and exceeding that sum fails the whole request

FieldTypeDescription
channels1array[bulk message channel object]Results in request order

1 Contains exactly one entry for each requested channel, in the order the entries were sent, and a duplicated channel ID therefore produces a duplicated result entry

StatusBodyCondition
200response bodyAll requested windows were returned
403error responseCaller is a bot and the request returns ACCESS_DENIED
403error responseThe caller lacks VIEW_CHANNEL for a requested channel and the request returns MISSING_PERMISSIONS
403error responseThe caller lacks age verification for a requested channel and the request returns NSFW_CONTENT_AGE_RESTRICTED
404error responseA requested channel does not exist or the caller is not a recipient of the private channel

20 requests per 10 seconds for each authenticated user, on the channel:messages:bulk_read bucket.

GET/v1/channels/{channel_id}/messages/{message_id}Bot

Returns one message object. Requires VIEW_CHANNEL.

  • In a guild channel without READ_MESSAGE_HISTORY, a message created before the guild’s message history cutoff is reported as 404 UNKNOWN_MESSAGE rather than 403.
FieldTypeDescription
channel_idsnowflakeThe ID of the channel
message_idsnowflakeThe ID of the message
StatusBodyCondition
200message objectMessage was returned
403error responseCaller lacks VIEW_CHANNEL and the request returns MISSING_PERMISSIONS, or the caller lacks age verification for the channel and the request returns NSFW_CONTENT_AGE_RESTRICTED
404error responseChannel or message does not exist, or the message is outside the caller’s message history cutoff

100 requests per 10 seconds for each authenticated user and channel ID, on the channel:message:read::channel_id bucket.

POST/v1/channels/{channel_id}/attachmentsBot

Plans from 1 through 10 attachment uploads. Returns a singlepart or multipart upload object for each declaration.

  • The channel must support messages, and one that does not fails with 400 CANNOT_SEND_MESSAGES_IN_NON_TEXT_CHANNEL.
  • A guild channel requires SEND_MESSAGES and ATTACH_FILES, and a timed-out member is refused with 403 COMMUNICATION_DISABLED.

Fluxer checks each declared file_size separately against the attachment size limit it resolves for the caller and the guild context. A declaration above that limit returns 400 FILE_SIZE_TOO_LARGE with the resolved ceiling. The resolved ceiling defaults to 26214400 bytes, the 25 MiB non-premium allowance, and 524288000 bytes, the 500 MiB premium allowance. A bot credential is additionally clamped to 52428800 bytes, the 50 MiB bot ceiling, even when the resolved limit is higher.

FieldTypeDescription
channel_idsnowflakeThe ID of the target message channel
FieldTypeDescription
attachmentsarray[attachment upload request item object]Attachment upload declarations (1-10 entries)
FieldTypeDescription
attachments1array[singlepart or multipart attachment upload object]Upload plan for each declaration

1 Returned in the same order as the request, and each entry echoes the caller’s id so a client can pair a plan with its declaration. Read upload_mode to select the variant

StatusBodyCondition
200response bodyUpload plans were issued
400error responseBody, attachment declaration, or count is invalid and the request returns INVALID_FORM_BODY
400error responseThe channel does not support messages and the request returns CANNOT_SEND_MESSAGES_IN_NON_TEXT_CHANNEL
400error responseA declared size exceeds the resolved limit and the request returns FILE_SIZE_TOO_LARGE
403error responseCaller lacks SEND_MESSAGES or ATTACH_FILES and the request returns MISSING_PERMISSIONS
403error responseThe caller is timed out and the request returns COMMUNICATION_DISABLED
403error responsePresigned attachment uploads are switched off for the instance and the request returns FEATURE_TEMPORARILY_DISABLED
404error responseChannel does not exist or is unavailable and the request returns UNKNOWN_CHANNEL, or the authenticated account does not exist and the request returns UNKNOWN_USER

The operation records one pending upload for each declaration against the caller and the channel, and opens a storage multipart upload for each multipart plan. It creates no message.

An issued upload_filename becomes an attachment only when a later Create message or Modify message request references it from a pre-uploaded attachment entry. A singlepart plan needs no completion step, so a message can reference its key as soon as the PUT succeeds.

10 requests per 10 seconds for each authenticated user and channel ID, on the channel:attachment:upload::channel_id bucket.

POST/v1/channels/{channel_id}/attachments/completeBot

Finalises from 1 through 10 multipart uploads after every part has been sent. Returns the finalised upload keys.

  • Each upload must have been planned as multipart by the same authenticated identity for the same channel.

The request has no part list and no entity tags.

FieldTypeDescription
channel_idsnowflakeThe ID of the channel bound to the uploads
FieldTypeDescription
uploadsarray[multipart upload completion item object]Uploads to finalise (1-10 entries)
FieldTypeDescription
uploadsarray[object]One entry for each finalised upload, each with upload_filename
StatusBodyCondition
200response bodyEvery multipart upload was finalised
400error responseBody is invalid, or an upload is not a pending multipart upload of this caller in this channel and the request returns INVALID_FORM_BODY with the code UPLOADED_ATTACHMENT_NOT_FOUND on the path uploads.{index}.upload_filename
400error responseNo part was uploaded and the request returns INVALID_FORM_BODY with the code NO_UPLOADED_PARTS_TO_FINALIZE on the path parts
400error responseThe uploaded bytes exceed the resolved limit and the request returns FILE_SIZE_TOO_LARGE
403error responseCaller lacks SEND_MESSAGES or ATTACH_FILES and the request returns MISSING_PERMISSIONS
403error responseThe caller is timed out and the request returns COMMUNICATION_DISABLED
403error responsePresigned attachment uploads are switched off for the instance and the request returns FEATURE_TEMPORARILY_DISABLED
404error responseChannel does not exist or is unavailable and the request returns UNKNOWN_CHANNEL, or the authenticated account does not exist and the request returns UNKNOWN_USER

The operation finalises each multipart upload and records its completion time and completion IP. It creates no message, and the upload key stays available until a message consumes it.

10 requests per 10 seconds for each authenticated user and channel ID, on the channel:attachment:upload::channel_id bucket, which is shared with Request attachment upload URLs.

POST/v1/channels/{channel_id}/messagesBot

Creates a message from a JSON body or from multipart form data. Returns the created message object. Emits a Message Create Gateway event.

  • The channel must be a text-bearing type.
  • A guild channel requires VIEW_CHANNEL and SEND_MESSAGES, an untimed-out membership, and any membership verification the guild requires.
  • A timed-out member is refused with 403 COMMUNICATION_DISABLED.
  • Embeds require EMBED_LINKS, attachments require ATTACH_FILES, a favourite meme requires both, and active everyone mentions require MENTION_EVERYONE.
  • Slowmode applies to a non-bot caller unless they hold BYPASS_SLOWMODE.
  • A one-to-one direct message additionally applies the recipient’s direct message policy and relationship state, and a denial returns 400 CANNOT_SEND_MESSAGES_TO_USER.
  • An unclaimed account can send only to its own personal notes channel, and a send to any other channel is refused with 400 UNCLAIMED_ACCOUNT_CANNOT_SEND_MESSAGES before the channel is resolved.
  • A non-bot caller must have started a session, and one that has not is refused with 400 MUST_START_SESSION_BEFORE_SENDING.

The request body is read as a multipart form when Content-Type contains multipart/form-data, and as JSON otherwise. An empty JSON body is read as {}. A JSON body that is neither valid JSON nor valid against the schema fails with 400 INVALID_MESSAGE_DATA on the path message_data, which has no per-field detail. A multipart body whose merged payload fails the same schema instead fails with a per-field 400 INVALID_FORM_BODY naming each offending path.

FieldTypeDescription
channel_idsnowflakeThe ID of the target channel
FieldTypeDescription
nonce?1string | integerCaller-generated identifier as a string of 1 through 32 characters or a non-negative safe integer
content?2?stringMessage text
embeds?6array[rich embed object]Rich embed inputs
attachments?7array[pre-uploaded attachment object]Attachment references
message_reference??message reference input objectReply or forward reference
allowed_mentions??allowed mentions objectActive mention policy
flags?3integerMessage flags, defaulting to 0
favorite_meme_id?4?snowflakeFavorite meme to attach
sticker_ids??array[snowflake]At most 3 sticker IDs
tts?5booleanWhether to request text-to-speech presentation

1 Echoed back on the created message and on its Message Create Dispatch so a client can match the result to its optimistic entry. An integer is converted to its decimal string form

2 The schema imposes no length bound. Exceeding the effective one returns 400 INVALID_FORM_BODY with CONTENT_EXCEEDS_MAX_LENGTH on the path content

3 Fluxer keeps only the bits in message flags and silently drops every other bit

4 The stored meme object is copied into a new attachment on the message, so the message has its own independent copy. A meme the caller does not own returns 400 INVALID_FORM_BODY with the code FAVORITE_MEME_NOT_FOUND

5 Fluxer forces the value to false when the caller lacks SEND_TTS_MESSAGES in a guild, and the request still succeeds

6 Bounded by the resolved max_embeds_per_message limit, which defaults to 10. Exceeding it fails with 400 TOO_MANY_EMBEDS on the path embeds

7 Bounded by the resolved max_attachments_per_message limit, which defaults to 10. Exceeding it fails with 400 TOO_MANY_FILES on the path attachments

The smallest body that works is one line of text:

{
"content": "hello"
}

Fluxer resolves the effective max_message_length for the author and guild context, and it defaults to 2,000 characters. A bot or webhook author takes whichever is larger, the resolved value or 4,000 characters.

A message must have at least one of content with visible characters, an embed, an attachment, a favourite meme, or a sticker, and an otherwise empty request fails with 400 CANNOT_SEND_EMPTY_MESSAGE. SUPPRESS_NOTIFICATIONS changes notification generation, and the message still has its mention data.

Reusing a nonce in the same channel inside that window returns the message the first request created. Reusing it in a different channel fails with 404 UNKNOWN_MESSAGE. The replay check runs after authorisation and body validation, so a retry that is otherwise invalid still fails, and a retry after the window has passed creates a second message.

A reply applies the caller’s message history cutoff to its target, and a forward applies none to its source. A reply whose target is a system message fails with 400 CANNOT_REPLY_TO_SYSTEM_MESSAGE, and a reference that resolves to no message fails with 404 UNKNOWN_MESSAGE.

A FORWARD reference has channel_id. One that does not is refused by body validation before the operation runs, with 400 INVALID_MESSAGE_DATA on a JSON body and a per-field 400 INVALID_FORM_BODY on a multipart body.

A forward request has no content, embeds, attachments, or sticker_ids, and one that does fails with 400 FORWARD_MESSAGES_CANNOT_CONTAIN_CONTENT. A guild_id that disagrees with the source channel’s guild fails with 400 GUILD_ID_MUST_MATCH_REFERENCED_MESSAGE. Reading the source channel requires VIEW_CHANNEL when that channel belongs to a guild.

Snapshots with embeds require EMBED_LINKS in the destination guild channel, and snapshots with attachments require ATTACH_FILES, each returning 403 MISSING_PERMISSIONS when absent.

FieldTypeDescription
payload_json?stringJSON encoding of the create message body, defaulting to {} when the field is absent
files[N]?1 2binaryDirect attachment file at zero-based index N
content?stringOverrides content in payload_json
nonce?stringOverrides nonce in payload_json
tts?stringOverrides tts in payload_json, parsed from true or false
flags?stringOverrides flags in payload_json, parsed as a decimal integer
favorite_meme_id?stringOverrides favorite_meme_id in payload_json
sticker_ids?stringOverrides sticker_ids in payload_json, repeated once per sticker

1 The legacy names file and file<N> are accepted and take the same indices. Any field name not listed above is ignored

2 The index runs from 0 through the resolved max_attachments_per_message limit minus one

A body that cannot be parsed as a multipart form fails with 400 FAILED_TO_PARSE_MULTIPART_FORM_DATA, and a payload_json field that is not a JSON string fails with 400 INVALID_JSON_IN_PAYLOAD_JSON. A field name beginning with files[ that does not match files[<N>] fails with 400 INVALID_FILE_FIELD_NAME.

File field conditionError
Index below 0 or above 10000400 FILE_INDEX_EXCEEDS_MAXIMUM reporting a maxIndex of 10000
Resolved attachment limit is 0400 ATTACHMENTS_NOT_ALLOWED_FOR_MESSAGE
Index at or above a non-zero resolved limit400 FILE_INDEX_EXCEEDS_MAXIMUM reporting that limit minus one
Index repeated across fields400 DUPLICATE_FILE_INDEX
More than one file under one index400 MULTIPLE_FILES_FOR_INDEX_NOT_ALLOWED
More files than the resolved limit400 TOO_MANY_FILES

The attachments array inside payload_json uses direct multipart attachment metadata, and an entry with upload_filename is instead read as a pre-uploaded attachment. An entry whose id matches a supplied file index supplies that file’s metadata, and two entries claiming the same file fail with 400 DUPLICATE_ATTACHMENT_IDS_NOT_ALLOWED.

Fluxer permits index gaps and attaches the files in ascending index order. A supplied file that no metadata entry claims is attached with its own multipart filename and no title or description, so omitting attachments entirely attaches every supplied file that way.

A message with VOICE_MESSAGE set has exactly one attachment and nothing else. Each rule fails with its own 400 code.

Any count other than one attachment returns VOICE_MESSAGES_REQUIRE_SINGLE_ATTACHMENT. A missing waveform returns VOICE_MESSAGES_ATTACHMENT_WAVEFORM_REQUIRED and a missing duration returns VOICE_MESSAGES_ATTACHMENT_DURATION_REQUIRED. Content, embeds, stickers, and a favourite meme return VOICE_MESSAGES_CANNOT_HAVE_CONTENT, VOICE_MESSAGES_CANNOT_HAVE_EMBEDS, VOICE_MESSAGES_CANNOT_HAVE_STICKERS, and VOICE_MESSAGES_CANNOT_HAVE_FAVORITE_MEMES. A duration above the resolved max_voice_message_duration limit, which defaults to 1200 seconds, returns VOICE_MESSAGES_DURATION_EXCEEDS_LIMIT.

StatusBodyCondition
200message objectMessage was created
400error responseBody, multipart form, content, reference, mention, attachment, embed, sticker, or voice message contract is invalid, the recipient’s direct message policy denies the send and the request returns CANNOT_SEND_MESSAGES_TO_USER, or slowmode denies the send and the request returns SLOWMODE_RATE_LIMITED
403error responseCaller lacks a required permission and the request returns MISSING_PERMISSIONS
403error responseIs timed out and the request returns COMMUNICATION_DISABLED
403error responseIs age restricted from the channel and the request returns NSFW_CONTENT_AGE_RESTRICTED
403error responseMessage sending is temporarily disabled for the guild and the request returns FEATURE_TEMPORARILY_DISABLED
404error responseChannel, referenced message, sticker, or guild does not exist or is unavailable, or the supplied nonce was last used in a different channel and the request returns UNKNOWN_MESSAGE

retry_after is never more than one second below the header. The response has no bucket headers and no X-RateLimit-Scope, so a client can tell it apart from a route or global limit denial.

The operation creates the message, attaches every referenced upload and direct multipart file, applies attachment decay deadlines, copies forwarded media, updates the channel’s last message, and makes the message searchable.

It advances the author’s read state unless the author is a bot, reopens a direct message for any recipient who had closed it, and resolves eligible uncached URLs into embeds.

It emits Message Create to every session that can see the channel. Mention and reply notifications follow the resolved allowed mentions policy.

It creates no audit log entry.

20 requests per 10 seconds for each authenticated user and channel ID, on the channel:message:create::channel_id bucket.

PATCH/v1/channels/{channel_id}/messages/{message_id}Bot

Modifies a message. Returns the updated message object. Emits a Message Update Gateway event.

  • The target must be a DEFAULT or REPLY message, and any other type fails with 400 CANNOT_MODIFY_SYSTEM_WEBHOOK.
  • A message that has message snapshots cannot be edited by its author and fails with 400 MESSAGES_WITH_SNAPSHOTS_CANNOT_BE_EDITED. A non-author moderator holding MANAGE_MESSAGES can still toggle SUPPRESS_EMBEDS and change existing attachment metadata on a forwarded message.
  • The author can modify every supported field, and a timed-out author is refused with 403 COMMUNICATION_DISABLED.
  • A caller who is not the author can act only in a guild channel, must hold MANAGE_MESSAGES, and can change only SUPPRESS_EMBEDS and the metadata of attachments that already exist. A non-author edit that does not satisfy all three conditions fails with 403 CANNOT_EDIT_OTHER_USER_MESSAGE.
  • MANAGE_MESSAGES is an elevated permission, so a caller holding the bit without an enrolled authenticator receives 400 TWO_FACTOR_REQUIRED in a guild whose MFA level is elevated, unless they own the guild. A caller who does not hold the bit at all is treated as any other non-author and receives 403 CANNOT_EDIT_OTHER_USER_MESSAGE.
  • Embeds require EMBED_LINKS and adding an upload requires ATTACH_FILES.
  • The route takes a per-message write lock for the duration of the edit. A request that cannot take the lock fails with 429 RESOURCE_LOCKED and a Retry-After of 1.

The body is read exactly as it is for Create message, so a multipart/form-data request is accepted with the same payload_json and files[N] fields. A file that is not uploaded directly must first be planned through Request attachment upload URLs and then referenced by its upload_filename.

FieldTypeDescription
channel_idsnowflakeThe ID of the channel
message_idsnowflakeThe ID of the message to modify
FieldTypeDescription
content??stringReplacement text under the same effective limits as message creation
embeds?1array[rich embed object]Replacement embed collection
allowed_mentions?2?allowed mentions objectReplacement active mention policy
flags?3integerReplacement message flags
attachments?1array[pre-uploaded attachment object | existing attachment reference object]Complete retained and added attachment collection

1 Replaces the stored collection outright, so an existing embed or attachment that the array omits is removed. Both collections are bounded by the same resolved limits as message creation

2 Defaults to the stored reply mention state when omitted, so an edit that does not name a policy neither adds nor removes the reply mention of the referenced author

3 Only the bits in message flags are retained, and the message keeps every other stored bit unchanged

A request that supplies message_snapshots is rejected with 403 MISSING_PERMISSIONS, so snapshot metadata cannot be edited through this route.

An omitted field preserves its stored value, and the message’s edited_timestamp advances only when content changes. The request itself must supply at least one of content with visible characters, an embed, an attachment, or flags, and one that supplies none of them fails with 400 CANNOT_SEND_EMPTY_MESSAGE.

An id that names no attachment on the message is skipped, and the edit still succeeds.

StatusBodyCondition
200message objectMessage was modified
400error responseBody, message type, attachment, embed, or resulting payload is invalid, or the author is editing a message that has snapshots and the request returns MESSAGES_WITH_SNAPSHOTS_CANNOT_BE_EDITED
403error responseCaller is not the author and cannot moderate the message and the request returns CANNOT_EDIT_OTHER_USER_MESSAGE
403error responseThe caller supplied message_snapshots or lacks EMBED_LINKS or ATTACH_FILES and the request returns MISSING_PERMISSIONS
403error responseThe caller is timed out and the request returns COMMUNICATION_DISABLED
403error responseThe caller is age restricted from the channel and the request returns NSFW_CONTENT_AGE_RESTRICTED
403error responseMessage sending is temporarily disabled for the guild and the request returns FEATURE_TEMPORARILY_DISABLED
404error responseChannel or message does not exist

The operation updates the message, advances its edit timestamp when content changed, attaches every newly referenced upload, and drops each attachment the request did not retain. It recalculates mentions when content, allowed_mentions, or embeds changed, updates search results when the channel is indexed, and resolves newly added eligible URLs into embeds.

It emits Message Update to every session that can see the channel. It creates no audit log entry, even for a moderator edit.

20 requests per 10 seconds for each authenticated user and channel ID, on the channel:message:update::channel_id bucket.

DELETE/v1/channels/{channel_id}/messages/ackBot

Deletes the authenticated identity’s read state entry for one channel. Returns 204 with an empty body on success.

  • Fluxer does not resolve the channel, so the operation mutates only the caller’s own read state.
  • The operation is idempotent, and a channel with no stored entry still returns 204.
FieldTypeDescription
channel_idsnowflakeThe ID of the channel whose read state is deleted
StatusBodyCondition
204emptyRead state was absent or deleted
403error responseCredential type or account state denies the request and it returns ACCESS_DENIED or ACCOUNT_SUSPICIOUS_ACTIVITY

The operation deletes the caller’s stored read-through marker, mention count, and pin acknowledgement for the channel, and invalidates the caller’s cached unread badge count. It emits no Gateway Dispatch.

40 requests per 10 seconds for each authenticated user and channel ID, on the channel:read_state:delete::channel_id bucket.

DELETE/v1/channels/{channel_id}/messages/{message_id}Bot

Deletes one message. Returns 204 with an empty body on success. Emits a Message Delete Gateway event.

  • The target must be a deletable message type.
  • The author can delete their own message anywhere.
  • Deleting another user’s guild message requires both SEND_MESSAGES and MANAGE_MESSAGES, and no caller can delete another user’s private channel message.
  • MANAGE_MESSAGES is an elevated permission, so a caller holding the bit without an enrolled authenticator receives 400 TWO_FACTOR_REQUIRED in a guild whose MFA level is elevated, unless they own the guild.
  • The operation reads no audit reason header.
FieldTypeDescription
channel_idsnowflakeThe ID of the channel
message_idsnowflakeThe ID of the message to delete
StatusBodyCondition
204emptyMessage was deleted
403error responseCaller lacks authorship or the required guild permissions, or the message type is not deletable, each returning MISSING_PERMISSIONS
403error responseThe caller lacks age verification for the channel and the request returns NSFW_CONTENT_AGE_RESTRICTED
403error responseMessage sending is temporarily disabled for the guild and the request returns FEATURE_TEMPORARILY_DISABLED
404error responseChannel or message does not exist

The operation permanently deletes the message, its reactions, and its attachments and removes it from search.

It emits Message Delete to every session that can see the channel. When the message was pinned, it also removes the channel pin entry and emits Channel Pins Update with the channel’s unchanged last-pin timestamp.

Every deletion in a guild channel writes one MESSAGE_DELETE guild audit log entry with no reason, including deletion of the caller’s own message.

20 requests per 10 seconds for each authenticated user and channel ID, on the channel:message:delete::channel_id bucket.

DELETE/v1/channels/{channel_id}/messages/{message_id}/attachments/{attachment_id}Bot

Deletes one attachment from the caller’s own message. Returns 204 with an empty body on success. Emits a Message Update Gateway event.

  • Only the message author can use this operation, and a guild moderator must use Modify message instead.
  • This route cannot address an attachment that a resolved embed owns.
  • When the attachment was the message’s last remaining payload, the Delete message effects apply.
FieldTypeDescription
channel_idsnowflakeThe ID of the channel
message_idsnowflakeThe ID of the owning message
attachment_idsnowflakeThe ID of the attachment to delete
StatusBodyCondition
204emptyAttachment or resulting empty message was deleted
403error responseCaller is not the message author and the request returns MISSING_PERMISSIONS, or message sending is temporarily disabled for the guild and the request returns FEATURE_TEMPORARILY_DISABLED
404error responseChannel or message does not exist, or the message has no such addressable attachment

The operation permanently deletes the stored attachment object, purges it from media delivery, removes it from the message, and advances the message’s edit timestamp. It then emits Message Update to every session that can see the channel. When the removal leaves the message with no payload, the complete Delete message effect set applies instead, including its Dispatches and guild audit log entry.

20 requests per 10 seconds for each authenticated user and channel ID, on the channel:message:delete::channel_id bucket.

POST/v1/channels/{channel_id}/messages/bulk-deleteBotMFA

Deletes from 1 through 100 messages in one guild channel. Returns 204 with an empty body on success. Emits one Message Delete Bulk Gateway event.

  • The channel must belong to a guild, and a private channel fails with 400 CANNOT_EXECUTE_ON_DM.
  • The caller requires MANAGE_MESSAGES.
  • MANAGE_MESSAGES is an elevated permission, so a caller holding the bit without an enrolled authenticator receives 400 TWO_FACTOR_REQUIRED in a guild whose MFA level is elevated, unless they own the guild.
  • The operation applies no age boundary, so a message of any age can be selected.
  • The operation reads no audit reason header.
FieldTypeDescription
channel_idsnowflakeThe ID of the guild channel

At least one of the two fields below must be present. Supplying neither fails with 400 INVALID_FORM_BODY on the path message_ids, and supplying both uses message_ids and ignores messages.

FieldTypeDescription
message_ids?1array[snowflake]Message IDs to delete, at most 100 entries
messages?1array[snowflake]Alias for message_ids

1 An empty array fails with 400 MESSAGE_IDS_CANNOT_BE_EMPTY on the path message_ids. More than 100 entries is rejected by body validation with 400 INVALID_FORM_BODY before the operation runs

An ID that names no message in the channel is skipped, so a partially matching request still deletes every matching message. When no ID matches, the request returns 204 without deleting anything, emitting a Dispatch, or writing an audit log entry.

StatusBodyCondition
204emptyMessages were deleted
400error responseBody or entry count is invalid, the selection is empty and the request returns MESSAGE_IDS_CANNOT_BE_EMPTY, or the channel is a private channel and the request returns CANNOT_EXECUTE_ON_DM
403error responseCaller lacks MANAGE_MESSAGES and the request returns MISSING_PERMISSIONS, or the caller lacks age verification for the channel and the request returns NSFW_CONTENT_AGE_RESTRICTED
404error responseChannel does not exist

The operation permanently removes every selected message, attachment, and reaction and removes each message from search.

When at least one ID matched, it emits one Message Delete Bulk with every requested ID to sessions that can see the channel, including an ID that matched nothing. It emits no Channel Pins Update and no individual Message Delete.

It writes one MESSAGE_BULK_DELETE guild audit log entry with the matched count and no reason.

10 requests per 10 seconds for each authenticated user and channel ID, on the channel:message:bulk_delete::channel_id bucket.

POST/v1/channels/{channel_id}/messages/purgeBot

Deletes every message in the authenticated user’s personal notes channel. Returns the number that were removed. Emits a Message Delete Bulk Gateway event.

  • The channel must be the caller’s own DM_PERSONAL_NOTES channel, and any other channel fails with 400 INVALID_CHANNEL_TYPE.

The deletion runs inside the request in pages of 100 messages, so a channel with a very large history holds the request open until the last message is gone.

FieldTypeDescription
channel_idsnowflakeThe ID of the personal notes channel
FieldTypeDescription
deleted_countintegerNumber of messages removed by this request
StatusBodyCondition
200response bodyEvery personal note was deleted
403error responseCredential type or account state denies the request and it returns ACCESS_DENIED or ACCOUNT_SUSPICIOUS_ACTIVITY
404error responseChannel does not exist or the caller cannot resolve it

The operation permanently deletes every personal note, its attachments, and its reactions and removes each from search. The caller’s sessions receive one Message Delete Bulk Dispatch for each page of at most 100 messages.

The operation emits no Channel Pins Update and no individual Message Delete, and it writes no audit log entry.

2 requests per minute for each authenticated user and channel ID, on the channel:message:purge::channel_id bucket.

POST/v1/channels/{channel_id}/messages/bulk-delete-mineBotMFA

Deletes every message the caller authored in one channel. Returns 202 with an empty body. Emits a Message Delete Bulk Gateway event.

  • User session and bot credentials are accepted, and a bot credential satisfies the sudo requirement without any proof.
  • The caller must be able to resolve the channel and must be in sudo mode, established by the X-Fluxer-Sudo-Mode-JWT header or by supplying a proof in the body.
  • A caller who satisfies none of those receives 403 SUDO_MODE_REQUIRED with has_mfa and the available methods.
  • An account that holds no verifiable credential at all, meaning it is not a bot, has no enrolled authenticator, and has no stored password, satisfies the sudo requirement with an empty body.

The deletion runs inside the request despite the 202 status, so every matching message is gone by the time the response is returned.

FieldTypeDescription
channel_idsnowflakeThe ID of the channel whose caller-authored messages are deleted
FieldTypeDescription
X-Fluxer-Sudo-Mode-JWT?1stringExisting sudo mode proof

1 A valid header satisfies the sudo requirement on its own, and the body fields below are then unnecessary. The accepted proof is echoed back in the same response header

FieldTypeDescription
password?1stringAccount password proof
mfa_method?2stringMFA method, one of totp or webauthn
mfa_code?stringAuthenticator code (1-32 characters), supplied with the totp method
webauthn_response?WebAuthn assertion objectWebAuthn assertion for sudo verification
webauthn_challenge?stringChallenge bound to the sudo mode assertion

1 Accepted only when the account has no enrolled authenticator, and an incorrect password fails with 400 INVALID_PASSWORD. An account with neither a stored password nor an enrolled authenticator never reaches this check

2 Accepted only when the account has an enrolled authenticator. A failed verification returns 400 INVALID_MFA_CODE

StatusBodyCondition
202emptyEvery caller-authored message in the channel was deleted
403error responseCaller is not in sudo mode and the request returns SUDO_MODE_REQUIRED
403error responseThe caller cannot view the guild channel and the request returns MISSING_PERMISSIONS
403error responseThe caller is age restricted from the channel and the request returns NSFW_CONTENT_AGE_RESTRICTED
404error responseChannel does not exist or is unavailable

Each matching message and its attachments are permanently deleted and removed from search. Deletions emit batched Message Delete Bulk Dispatches.

The operation emits no Channel Pins Update and no individual Message Delete, and it writes no guild audit log entry.

10 requests per 10 seconds for each authenticated user and channel ID, on the channel:message:bulk_delete::channel_id bucket.

GET/v1/channels/{channel_id}/messages/pinsBot

Returns a channel pins page object holding one page of pinned messages and their pin times.

  • The caller must be able to view the channel and must satisfy the channel’s age verification requirement.
  • The channel must be a text-bearing type.
  • A guild caller without READ_MESSAGE_HISTORY sees only pins whose message falls on or after the guild’s message history cutoff, and receives an empty page when the guild has no cutoff.
FieldTypeDescription
channel_idsnowflakeThe ID of the channel whose pins are returned
FieldTypeDescription
limit?integerNumber of pins to return (1-50, default 50)
before?ISO8601 timestampReturn pins pinned before this timestamp, defaulting to the current time
StatusBodyCondition
200channel pins page objectPin page was returned
400error responsePath or cursor is invalid, or the channel has no messages and the request returns CANNOT_SEND_MESSAGES_IN_NON_TEXT_CHANNEL
403error responseCaller lacks VIEW_CHANNEL and the request returns MISSING_PERMISSIONS, or the caller lacks age verification for the channel and the request returns NSFW_CONTENT_AGE_RESTRICTED
404error responseChannel does not exist or the caller is not a recipient of the private channel

Acknowledging pins is a separate operation, Acknowledge pins.

20 requests per 10 seconds for each authenticated user and channel ID, on the channel:pins::channel_id bucket.

PUT/v1/channels/{channel_id}/pins/{message_id}Bot

Pins a DEFAULT or REPLY message. Returns 204 with an empty body on success. Emits Message Update, Channel Pins Update, and Message Create Gateway events.

  • A guild caller requires PIN_MESSAGES and channel access.
  • A guild caller without READ_MESSAGE_HISTORY can pin only a message on or after the guild’s message history cutoff.
  • A one-to-one direct message caller must satisfy the recipient’s direct message policy, and one who may not send fails with 400 CANNOT_SEND_MESSAGES_TO_USER.
  • A group direct message and the personal notes channel apply no send policy.
  • The operation is idempotent.
FieldTypeDescription
channel_idsnowflakeThe ID of the channel
message_idsnowflakeThe ID of the message to pin
StatusBodyCondition
204emptyMessage was already pinned or was pinned
400error responsePath is invalid and the request returns INVALID_FORM_BODY
400error responseThe channel has no messages and the request returns CANNOT_SEND_MESSAGES_IN_NON_TEXT_CHANNEL
400error responseThe target is a system message and the request returns CANNOT_MODIFY_SYSTEM_WEBHOOK
400error responseThe private channel’s send policy denies the caller and the request returns CANNOT_SEND_MESSAGES_TO_USER
403error responseCaller lacks VIEW_CHANNEL or PIN_MESSAGES and the request returns MISSING_PERMISSIONS, or message sending is temporarily disabled for the guild and the request returns FEATURE_TEMPORARILY_DISABLED
404error responseChannel or message does not exist, or the message is outside the caller’s message history cutoff

Pinning a message that is not already pinned sets its pin timestamp, advances the channel’s last-pin timestamp, and stores a new CHANNEL_PINNED_MESSAGE system message authored by the caller and referencing the pinned message.

It emits Message Update for the target, Channel Pins Update for the channel, and Message Create for the system message, each to every session that can see the channel.

A guild pin also writes one MESSAGE_PIN guild audit log entry with no reason. Pinning an already pinned message changes nothing and emits no Dispatch.

20 requests per 10 seconds for each authenticated user and channel ID, on the channel:pins::channel_id bucket.

DELETE/v1/channels/{channel_id}/pins/{message_id}Bot

Unpins a message. Returns 204 with an empty body on success. Emits Message Update and Channel Pins Update Gateway events.

  • Authorisation is exactly the same as Pin message.
  • The operation is idempotent.
FieldTypeDescription
channel_idsnowflakeThe ID of the channel
message_idsnowflakeThe ID of the message to unpin
StatusBodyCondition
204emptyMessage was already unpinned or was unpinned
400error responsePath is invalid and the request returns INVALID_FORM_BODY
400error responseThe channel has no messages and the request returns CANNOT_SEND_MESSAGES_IN_NON_TEXT_CHANNEL
400error responseThe target is a system message and the request returns CANNOT_MODIFY_SYSTEM_WEBHOOK
400error responseThe private channel’s send policy denies the caller and the request returns CANNOT_SEND_MESSAGES_TO_USER
403error responseCaller lacks VIEW_CHANNEL or PIN_MESSAGES and the request returns MISSING_PERMISSIONS, or message sending is temporarily disabled for the guild and the request returns FEATURE_TEMPORARILY_DISABLED
404error responseChannel or message does not exist, or the message is outside the caller’s message history cutoff

Unpinning a currently pinned message clears its pin timestamp and emits Message Update and Channel Pins Update to every session that can see the channel. A guild unpin also writes one MESSAGE_UNPIN guild audit log entry with no reason.

It creates no system message. The CHANNEL_PINNED_MESSAGE system message the original pin created stays in the channel, and the channel’s last-pin timestamp is unchanged.

20 requests per 10 seconds for each authenticated user and channel ID, on the channel:pins::channel_id bucket.

POST/v1/channels/{channel_id}/pins/ackBot

Records the channel’s current pin timestamp in the authenticated identity’s read state. Returns 204 with an empty body. Emits a Channel Pins ACK Gateway event.

The request has no body. Fluxer acknowledges the channel’s own stored last-pin timestamp.

FieldTypeDescription
channel_idsnowflakeThe ID of the channel whose current pin state is acknowledged
StatusBodyCondition
204emptyPin state was absent or acknowledged
403error responseCredential type or account state denies the request and it returns ACCESS_DENIED or ACCOUNT_SUSPICIOUS_ACTIVITY

When the channel stores a last-pin timestamp, Fluxer writes that exact instant to the caller’s read state and emits one Channel Pins ACK with the channel ID and that timestamp to the caller’s own sessions. The write replaces the stored value. When the channel stores no last-pin timestamp, Fluxer writes nothing and emits nothing.

When the Dispatch fails, the request returns 502, 503, or 504 after the read-state write has landed. A client treats those statuses as indeterminate and reconciles from a later read.

20 requests per 10 seconds for each authenticated user and channel ID, on the channel:pins::channel_id bucket, which is shared with List pinned messages, Pin message, and Unpin message.

The emoji path value is URI-encoded and is 1 through 64 characters. A custom emoji uses name:id, where id is the trailing decimal custom emoji snowflake and name is everything before the final colon. Any other decoded value is read as a Unicode emoji.

Fluxer validates the emoji in full only when a request would create a new reaction group on the message. At that point a Unicode value must be exactly one valid emoji, and one that is not fails with 400 NOT_A_VALID_UNICODE_EMOJI. A custom emoji must exist, and one that does not fails with 400 CUSTOM_EMOJI_NOT_FOUND. Every other reaction operation parses the value without validating it, so removing a reaction with a nonsensical emoji succeeds silently.

GET/v1/channels/{channel_id}/messages/{message_id}/reactions/{emoji}Bot

Returns a bare array of partial user objects for one ordinary reaction.

  • Authorisation, query parameters, and ordering are exactly those of List reaction users, and the array is the same page that operation returns in its items field.

The pagination signal is in two response headers. X-Has-More is true or false. X-Next-After is the ID of the last user in the array, and it is absent when no further page exists. List reaction users returns the same users with both values in the body.

FieldTypeDescription
channel_idsnowflakeThe ID of the channel
message_idsnowflakeThe ID of the message
emojistringURI-encoded reaction emoji path value
FieldTypeDescription
limit?integerNumber of users to return (1-100, default 25)
after?snowflakeReturn users after this user ID cursor
StatusBodyCondition
200array[partial user object]Reaction users were returned
400error responsePath, emoji, or pagination input is invalid, or the channel has no messages and the request returns CANNOT_SEND_MESSAGES_IN_NON_TEXT_CHANNEL
403error responseCaller lacks VIEW_CHANNEL and the request returns MISSING_PERMISSIONS
404error responseChannel or message does not exist, or the message is outside the caller’s message history cutoff

An emoji with no reaction group on the message returns 200 with an empty array.

30 requests per 10 seconds for each authenticated user and channel ID, on the channel:reactions::channel_id bucket.

GET/v1/channels/{channel_id}/messages/{message_id}/reactions/{emoji}/usersBot

Returns a reaction users page object holding the users who added one ordinary reaction.

  • The caller must be able to view the channel, and the channel must be a text-bearing type.
  • A guild caller without READ_MESSAGE_HISTORY can read only a message on or after the guild’s message history cutoff.
FieldTypeDescription
channel_idsnowflakeThe ID of the channel
message_idsnowflakeThe ID of the message
emojistringURI-encoded reaction emoji path value
FieldTypeDescription
limit?integerNumber of users to return (1-100, default 25)
after?snowflakeReturn users after this user ID cursor
StatusBodyCondition
200reaction users page objectReaction users were returned
400error responsePath, emoji, or pagination input is invalid, or the channel has no messages and the request returns CANNOT_SEND_MESSAGES_IN_NON_TEXT_CHANNEL
403error responseCaller lacks VIEW_CHANNEL and the request returns MISSING_PERMISSIONS
404error responseChannel or message does not exist, or the message is outside the caller’s message history cutoff

An emoji with no reaction group on the message returns 200 with an empty items array, has_more false, and a null next_after.

30 requests per 10 seconds for each authenticated user and channel ID, on the channel:reactions::channel_id bucket.

PUT/v1/channels/{channel_id}/messages/{message_id}/reactions/{emoji}/@meBot

Adds the authenticated identity’s ordinary reaction. Returns 204 with an empty body. Emits a Message Reaction Add Gateway event.

  • The caller must be able to view the text-bearing channel, must not be timed out, and must reach the message under the message history cutoff.
  • A non-bot caller must have a verified email, and one that does not receives 403 REACTION_EMAIL_VERIFICATION_REQUIRED.
  • Creating a new emoji reaction group in a guild requires ADD_REACTIONS, while adding to an existing group does not.
  • A custom emoji whose source guild is not the channel’s guild requires the feature_global_expressions entitlement, and a caller without it receives 400 CUSTOM_EMOJIS_REQUIRE_PREMIUM_OUTSIDE_SOURCE.
  • In a guild channel a custom emoji additionally requires USE_EXTERNAL_EMOJIS.
  • A non-bot caller must have started a session, and one that has not receives 400 MUST_START_SESSION_BEFORE_SENDING.
  • An unclaimed account can react only in its personal notes channel, and elsewhere receives 400 UNCLAIMED_ACCOUNT_CANNOT_ADD_REACTIONS.
  • The operation is idempotent, and this route applies no direct message send policy.
FieldTypeDescription
channel_idsnowflakeThe ID of the channel
message_idsnowflakeThe ID of the message
emojistringURI-encoded reaction emoji path value
FieldTypeDescription
session_id?1stringOriginating Gateway session ID (1-64 characters)

1 Echoed in the resulting Dispatch so the originating session can correlate its own optimistic update, and it never affects authorisation or the stored reaction

A message has at most the resolved max_reactions_per_message distinct reaction groups, which defaults to 30, and one group at most the resolved max_users_per_message_reaction users, which defaults to 1,000,000. Both ceilings are reported as 400 MAX_REACTIONS.

StatusBodyCondition
204emptyReaction already existed or was added
400error responsePath, emoji, or session is invalid, the channel has no messages and the request returns CANNOT_SEND_MESSAGES_IN_NON_TEXT_CHANNEL
400error responseThe account has not started a session and the request returns MUST_START_SESSION_BEFORE_SENDING
400error responseThe account is unclaimed and the request returns UNCLAIMED_ACCOUNT_CANNOT_ADD_REACTIONS
400error responseThe emoji is not a valid single Unicode emoji and the request returns NOT_A_VALID_UNICODE_EMOJI
400error responseThe custom emoji is unknown and the request returns CUSTOM_EMOJI_NOT_FOUND
400error responseThe external emoji requires the entitlement and the request returns CUSTOM_EMOJIS_REQUIRE_PREMIUM_OUTSIDE_SOURCE
400error responseThe message has reached a reaction ceiling and the request returns MAX_REACTIONS
403error responseCaller lacks VIEW_CHANNEL, ADD_REACTIONS, or USE_EXTERNAL_EMOJIS and the request returns MISSING_PERMISSIONS
403error responseThe caller is timed out and the request returns COMMUNICATION_DISABLED
403error responseThe caller has an unverified email and the request returns REACTION_EMAIL_VERIFICATION_REQUIRED
403error responseReactions are temporarily disabled for the guild and the request returns FEATURE_TEMPORARILY_DISABLED
404error responseChannel or message does not exist, or the message is outside the caller’s message history cutoff

Adding a reaction the caller does not already hold creates it and emits Message Reaction Add to every session that can see the channel, with session_id for originating session correlation. Adding a reaction the caller already has changes nothing and emits no Dispatch. It writes no audit log entry.

30 requests per 10 seconds for each authenticated user and channel ID, on the channel:reactions::channel_id bucket.

DELETE/v1/channels/{channel_id}/messages/{message_id}/reactions/{emoji}/@meBot

Removes the authenticated identity’s own ordinary reaction. Returns 204 with an empty body. Emits a Message Reaction Remove Gateway event.

  • The caller must be able to view the text-bearing channel and reach the message under the message history cutoff.
  • A removal re-runs none of the timeout, email verification, and emoji validity checks.
  • The operation is idempotent.
FieldTypeDescription
channel_idsnowflakeThe ID of the channel
message_idsnowflakeThe ID of the message
emojistringURI-encoded reaction emoji path value
FieldTypeDescription
session_id?1stringOriginating Gateway session ID (1-64 characters)

1 Echoed in the resulting Dispatch so the originating session can correlate its own optimistic update, and it never affects authorisation

StatusBodyCondition
204emptyReaction was absent or removed
400error responsePath, emoji, or session input is invalid, or the channel has no messages and the request returns CANNOT_SEND_MESSAGES_IN_NON_TEXT_CHANNEL
403error responseCaller lacks VIEW_CHANNEL and the request returns MISSING_PERMISSIONS, or reactions are temporarily disabled for the guild and the request returns FEATURE_TEMPORARILY_DISABLED
404error responseChannel does not exist, or the message is outside the caller’s message history cutoff

A message that does not exist returns 204 rather than 404.

Fluxer deletes the reaction and emits Message Reaction Remove to every session that can see the channel, with session_id for originating session correlation. The Dispatch is emitted whether or not the caller held the reaction.

30 requests per 10 seconds for each authenticated user and channel ID, on the channel:reactions::channel_id bucket.

DELETE/v1/channels/{channel_id}/messages/{message_id}/reactions/{emoji}/{target_id}Bot

Removes one named user’s ordinary reaction. Returns 204 with an empty body. Emits a Message Reaction Remove Gateway event.

  • The caller must be able to view the text-bearing channel and reach the message under the message history cutoff.
  • The message author may remove any user’s reaction from their own message in any channel.
  • Any other caller must be in a guild channel and must hold MANAGE_MESSAGES, so a non-author in a private channel is refused with 403 MISSING_PERMISSIONS.
  • MANAGE_MESSAGES is an elevated permission, so a caller holding the bit without an enrolled authenticator receives 400 TWO_FACTOR_REQUIRED in a guild whose MFA level is elevated, unless they own the guild.
  • The operation is idempotent.
FieldTypeDescription
channel_idsnowflakeThe ID of the channel
message_idsnowflakeThe ID of the message
emojistringURI-encoded reaction emoji path value
target_id1snowflakeThe ID of the user whose reaction is removed

1 Naming the authenticated user skips the moderation check entirely, so MANAGE_MESSAGES is not required in that case

FieldTypeDescription
session_id?1stringOriginating Gateway session ID (1-64 characters)

1 Echoed in the resulting Dispatch so the originating session can correlate its own optimistic update, and it never affects authorisation

StatusBodyCondition
204emptyTarget reaction was absent or removed
400error responsePath, emoji, or session input is invalid, or the channel has no messages and the request returns CANNOT_SEND_MESSAGES_IN_NON_TEXT_CHANNEL
403error responseCaller is not the message author and lacks VIEW_CHANNEL or MANAGE_MESSAGES, or is not the author in a private channel, each returning MISSING_PERMISSIONS, or reactions are temporarily disabled for the guild and the request returns FEATURE_TEMPORARILY_DISABLED
404error responseChannel does not exist, or the message is outside the caller’s message history cutoff

A message that does not exist returns 204 before the authorship and permission checks. A request naming a target user with no such reaction also returns 204.

Fluxer deletes the target user’s reaction and emits Message Reaction Remove with the target user ID to every session that can see the channel, plus session_id when the request supplied one. The Dispatch is emitted whether or not the target held the reaction. It creates no audit log entry.

30 requests per 10 seconds for each authenticated user and channel ID, on the channel:reactions::channel_id bucket.

DELETE/v1/channels/{channel_id}/messages/{message_id}/reactions/{emoji}Bot

Removes every ordinary reaction for one emoji. Returns 204 with an empty body. Emits a Message Reaction Remove Emoji Gateway event.

  • The caller must be able to view the text-bearing channel and reach the message under the message history cutoff.
  • The message author may clear the emoji on their own message in any channel.
  • Any other caller must be in a guild channel and must hold MANAGE_MESSAGES.
  • MANAGE_MESSAGES is an elevated permission, so a caller holding the bit without an enrolled authenticator receives 400 TWO_FACTOR_REQUIRED in a guild whose MFA level is elevated, unless they own the guild.
  • The operation is idempotent.
FieldTypeDescription
channel_idsnowflakeThe ID of the channel
message_idsnowflakeThe ID of the message
emojistringURI-encoded reaction emoji path value
StatusBodyCondition
204emptyEmoji reactions were absent or removed
400error responsePath or emoji is invalid, or the channel has no messages and the request returns CANNOT_SEND_MESSAGES_IN_NON_TEXT_CHANNEL
403error responseCaller is not the message author and lacks VIEW_CHANNEL or MANAGE_MESSAGES, or is not the author in a private channel, each returning MISSING_PERMISSIONS, or reactions are temporarily disabled for the guild and the request returns FEATURE_TEMPORARILY_DISABLED
404error responseChannel does not exist, or the message is outside the caller’s message history cutoff

Fluxer deletes every reaction for the emoji and emits one Message Reaction Remove Emoji to every session that can see the channel. Fluxer emits no Message Reaction Remove for the individual users. The Dispatch is emitted whether or not the message had a group for the emoji. It creates no audit log entry.

30 requests per 10 seconds for each authenticated user and channel ID, on the channel:reactions::channel_id bucket.

DELETE/v1/channels/{channel_id}/messages/{message_id}/reactionsBot

Removes every ordinary reaction from a message. Returns 204 with an empty body. Emits a Message Reaction Remove All Gateway event.

  • The caller must be able to view the text-bearing channel and reach the message under the message history cutoff.
  • The message author may clear their own message in any channel.
  • Any other caller must be in a guild channel and must hold MANAGE_MESSAGES.
  • MANAGE_MESSAGES is an elevated permission, so a caller holding the bit without an enrolled authenticator receives 400 TWO_FACTOR_REQUIRED in a guild whose MFA level is elevated, unless they own the guild.
  • The operation is idempotent.
FieldTypeDescription
channel_idsnowflakeThe ID of the channel
message_idsnowflakeThe ID of the message
StatusBodyCondition
204emptyReactions were absent or removed
400error responsePath parameters are invalid, or the channel has no messages and the request returns CANNOT_SEND_MESSAGES_IN_NON_TEXT_CHANNEL
403error responseCaller is not the message author and lacks VIEW_CHANNEL or MANAGE_MESSAGES, or is not the author in a private channel, each returning MISSING_PERMISSIONS, or reactions are temporarily disabled for the guild and the request returns FEATURE_TEMPORARILY_DISABLED
404error responseChannel does not exist, or the message is outside the caller’s message history cutoff

Fluxer deletes every reaction on the message and emits one Message Reaction Remove All to every session that can see the channel. Fluxer emits no event for the individual groups or users. The Dispatch is emitted whether or not the message had any reaction. It creates no audit log entry.

30 requests per 10 seconds for each authenticated user and channel ID, on the channel:reactions::channel_id bucket.

POST/v1/channels/{channel_id}/typingBot

Publishes typing activity in a text-bearing channel. Returns 204 with an empty body. Emits a Typing Start Gateway event.

  • The caller must hold SEND_MESSAGES in a guild channel and must not be timed out.
  • A private channel caller needs only recipient access, because this route applies no direct message send policy.
FieldTypeDescription
channel_idsnowflakeThe ID of the channel in which typing is indicated
StatusBodyCondition
204emptyTyping operation was accepted
400error responsePath parameter is invalid, or the channel has no messages and the request returns CANNOT_SEND_MESSAGES_IN_NON_TEXT_CHANNEL
403error responseCaller lacks SEND_MESSAGES and the request returns MISSING_PERMISSIONS, or the caller is timed out and the request returns COMMUNICATION_DISABLED
404error responseChannel does not exist or the caller is not a recipient of the private channel

The operation emits Typing Start to every session that can see the channel, with the channel ID, the caller’s user ID, and a Unix timestamp in seconds. It creates no durable state, so no read operation reports a typing indicator and the indicator expires on the client. When the guild has typing events disabled, the response is still 204 and no Dispatch is emitted.

20 requests per 10 seconds for each authenticated user and channel ID, on the channel:typing::channel_id bucket.

POST/v1/channels/{channel_id}/messages/{message_id}/ack

Advances the authenticated user’s read state through one message. Returns 204 with an empty body. Emits a Message ACK Gateway event.

  • This is a user-only operation, and a bot credential is refused with 403 ACCESS_DENIED.
  • Fluxer resolves neither the channel nor the message, so the operation writes the supplied identifiers straight into the caller’s own read state and mutates nothing else.
FieldTypeDescription
channel_id1snowflakeThe ID of the channel
message_id1snowflakeMessage ID through which the channel is acknowledged

1 Neither identifier needs to name something that exists, because both are stored as read-state keys and watermarks

An empty body is read as {}, and {} is the minimal valid form.

FieldTypeDescription
mention_count?1integerMention count to store for the channel (0-2,147,483,647, default 0)
manual?2booleanWhether the acknowledgement was explicitly initiated by the user (default false)

1 Fluxer stores the value verbatim. A client that acknowledges partway through a channel must send the number of mentions that remain above the watermark, and one that omits the field resets the stored count to 0

2 Selects the watermark rule described below

StatusBodyCondition
204emptyMessage was acknowledged
403error responseCaller is a bot and the request returns ACCESS_DENIED

The operation stores the new read-through marker and the supplied mention count for the caller and channel. It invalidates the caller’s cached unread badge count, clears the channel’s delivered notifications through the acknowledged watermark, and emits Message ACK to the caller’s own sessions only. No message state is modified.

A non-manual acknowledgement whose message_id is below the stored watermark leaves the stored watermark and mention count untouched. The Dispatch reports the stored values.

100 requests per 10 seconds for each authenticated user and channel ID, on the channel:message:ack::channel_id bucket.