Admin messages
Admin message routes read, search, and permanently delete the messages of one channel. Another reports the progress of a shred job.
Shredding and bulk deletion for a whole account live under Admin users.
Admin message object
Section titled “Admin message object”A flattened moderation view of one message. It has the author identity, the content and timestamp, the attachments, and the NSFW context of the channel and guild.
Every operation that returns Admin message objects also returns the matching public message objects in a parallel message_responses array, so a client that needs the full wire shape joins on id.
A message_responses entry has no thread field, and a thread started from a message lists no THREAD_STARTER_MESSAGE. Thread messages defines both.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| id | snowflake | The ID of the message |
| channel_id | snowflake | The channel the message was sent in |
| channel_name1 | ?string | The channel name, or null for a channel that has no name |
| channel_nsfw1 | ?boolean | Whether the channel is marked NSFW |
| channel_content_warning_level?2 | ?integer | The channel content warning level |
| channel_content_warning_text?2 | ?string | The channel content warning text (0-200 characters) |
| guild_id1 | ?snowflake | The guild containing the channel, or null for a private channel |
| guild_name1 | ?string | The guild name, or null for a private channel |
| guild_nsfw_level1 | ?integer | The guild NSFW level, or null for a private channel |
| guild_nsfw?2 | ?boolean | Whether the guild is marked NSFW |
| guild_content_warning_level?2 | ?integer | The guild content warning level |
| guild_content_warning_text?2 | ?string | The guild content warning text (0-200 characters) |
| author_id | snowflake | The ID of the author |
| author_username | string | The author username (1-100 characters) |
| author_global_name | ?string | The author display name, or null when unset |
| author_discriminator | string | The author discriminator tag (1-10 characters) |
| author_avatar | ?string | The author avatar hash, or null when unset |
| content | string | The message content (0-4,000 characters) |
| timestamp | ISO8601 timestamp | When the message was sent |
| attachments | array[Admin message attachment object] | The attachments of the message (at most 10) |
1 Every object in one response has the same values, taken from the channel named in the request path or query. All are null when the channel no longer exists
2 Always absent from the objects these operations return. The same member is set on the report message context object
For a thread, channel_nsfw is the value of its parent channel, as Thread object describes.
Example
Section titled “Example”{ "id": "1502771119476146176", "channel_id": "1471002884199612420", "channel_name": "general", "channel_nsfw": false, "guild_id": "1471002884199612416", "guild_name": "Tidepool", "guild_nsfw_level": 0, "author_id": "1490118377238528000", "author_username": "kestrel", "author_global_name": null, "author_discriminator": "0117", "author_avatar": "a1b2c3d4e5f60718293a4b5c6d7e8f90", "content": "read the pinned message", "timestamp": "2026-03-04T18:19:07.220Z", "attachments": []}Admin message attachment object
Section titled “Admin message attachment object”An attachment entry has the ordinary attachment metadata.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| id | snowflake | The ID of the attachment |
| filename | string | The attachment filename (1-256 characters) |
| url | string | The CDN URL of the attachment (1-2,048 characters) |
| nsfw | ?boolean | Whether the attachment is marked NSFW, or null when it has no marking |
| content_type | ?string | The recorded MIME type, or null when none was recorded |
| width | ?integer | The pixel width, or null when no dimensions were recorded |
| height | ?integer | The pixel height, or null when no dimensions were recorded |
| size?3 | ?integer | The attachment size in bytes, or null when no size was recorded |
3 Always emitted, so it is null and never absent when no size was recorded
Message shred status object
Section titled “Message shred status object”The state of one message shred job. The state expires one hour after it was last written, and an expired job is reported by status alone.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| status | not_found | in_progress | completed | failed | The job state |
| requested1 | integer | The number of message references the job was queued with |
| total1 | integer | The number of those references the job resolved as shreddable |
| processed1 | integer | The number of messages the job has shredded so far |
| skipped1 2 | integer | The number of references the job did not shred |
| started_at?1 3 | ISO8601 timestamp | When the job started |
| completed_at?1 | ISO8601 timestamp | When the job completed |
| failed_at?1 | ISO8601 timestamp | When the job failed |
| error?1 4 | string | Why the job failed (1-4,000 characters) |
1 Absent when status is not_found, a shape that has status alone
2 Counts a reference that repeats an earlier entry, one whose IDs are not valid snowflakes, one whose message no longer exists, and one no longer authored by the target user
3 Present whenever the counters are
4 Present only when status is failed
List channel messages
Section titled “List channel messages”GET/v1/admin/channels/{channel_id}/messagesReturns one page of Admin message objects for one channel. Requires message:lookup.
The read ignores message history permissions, channel membership, and the age cutoff applied to ordinary members, so it returns every message the channel still holds.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | The ID of the channel |
Query parameters
Section titled “Query parameters”| Field | Type | Description |
|---|---|---|
| limit? | integer | Maximum messages to return (1-100, default 50) |
| before?1 | snowflake | Return messages with a lower ID than this cursor |
| after?1 2 | snowflake | Return messages with a higher ID than this cursor |
1 Supplying neither selects the newest messages in the channel. Supplying both selects the newest messages below before and discards any at or below after
2 Supplying after also flips the order of the returned array
Response body
Section titled “Response body”| Field | Type | Description |
|---|---|---|
| messages1 | array[Admin message object] | Messages in this page (at most 100) |
| message_responses?2 | array[message object] | The same messages in the public wire shape, same order (at most 100) |
| has_more3 | boolean | Whether the page was filled to limit |
1 Ordered oldest first, except when after was supplied, in which case it is ordered newest first
2 Written by every response this operation produces
3 True when the page holds exactly limit entries, so a page that ends on the last message reports true and the next request returns an empty page
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | response body | Message page was returned |
The response has no cursor member. Page further by sending the ID of the oldest returned message as before, or the ID of the newest returned message as after.
A channel that does not exist returns an empty messages array with has_more false, so this operation never answers 404.
Side effects
Section titled “Side effects”One Admin audit entry is recorded with the action list_channel_messages, the target type channel, and the channel ID as the target. Its metadata keys are limit, result_count for the messages in this page, and has_more. A supplied before or after cursor is added under the same key.
Rate limit
Section titled “Rate limit”100 requests per minute for each authenticated user, on the shared admin:message:operation bucket.
Get message
Section titled “Get message”GET/v1/admin/channels/{channel_id}/messages/{message_id}Returns the requested message together with the messages surrounding it, as one array of Admin message objects, oldest first. Requires message:lookup.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | The ID of the channel |
| message_id | snowflake | The ID of the message |
Query parameters
Section titled “Query parameters”| Field | Type | Description |
|---|---|---|
| context_limit?1 | integer | Size of the whole returned window, counting the requested message (1-100, default 50) |
1 At most context_limit divided by two, rounded down, are newer than the requested message and the rest are older, so the default returns at most 25 newer and 24 older
Response body
Section titled “Response body”| Field | Type | Description |
|---|---|---|
| messages1 | array[Admin message object] | The requested message and its surrounding window (at most 100) |
| message_responses? | array[message object] | The same messages in the public wire shape, same order (at most 100) |
| message_id2 | ?snowflake | The requested message ID |
1 The requested message is one entry of this array, and it is absent when it no longer exists
2 Echoes the path parameter and is never null here
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | response body | Window was returned |
An unknown message returns 200 with the window surrounding the position the missing ID would have occupied, so this operation never returns UNKNOWN_MESSAGE. An unknown channel returns 200 with an empty messages array.
Side effects
Section titled “Side effects”One Admin audit entry is recorded with the action get_message, the target type message, and the message ID as the target. Its metadata keys are channel_id, context_limit, result_count for the messages returned, and found, which is true when the requested message is in messages and false otherwise.
Rate limit
Section titled “Rate limit”100 requests per minute for each authenticated user, on the shared admin:message:operation bucket.
Delete message
Section titled “Delete message”DELETE/v1/admin/channels/{channel_id}/messages/{message_id}Permanently deletes one message and purges the attachments it owned. Requires message:delete.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | The ID of the channel |
| message_id | snowflake | The ID of the message |
Response body
Section titled “Response body”| Field | Type | Description |
|---|---|---|
| success | boolean | Always true |
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | response body | Request completed and the audit entry was written |
An unknown channel or message returns 200 with success true and still records an audit entry.
Side effects
Section titled “Side effects”The message and its attachments are permanently removed, including from search results and the CDN.
Message Delete is sent to the guild when the channel belongs to one, and to each recipient when the channel is private. No other Dispatch is emitted, and deleting a pinned message here emits no Channel Pins Update.
A deleted message in a thread no longer counts towards message_count of the thread object. Fluxer emits no Thread Update for the change.
One Admin audit entry is recorded with the action delete_message and the target type message, targeting the message ID. Its metadata is channel_id and message_id. The entry is written whether or not a message was found.
Rate limit
Section titled “Rate limit”100 requests per minute for each authenticated user, on the shared admin:message:operation bucket.
Search messages
Section titled “Search messages”GET/v1/admin/messagesSearches the message index of one channel, or resolves one message in that channel by message ID or by attachment identity. Requires message:lookup.
A request with message_id or attachment_id returns the lookup response body. Any other request returns the search response body.
Query parameters
Section titled “Query parameters”| Field | Type | Description |
|---|---|---|
| channel_id | snowflake | The channel every returned message was sent in |
| q?1 | string | Free-text query matched against message content (1-200 characters) |
| message_id?2 | snowflake | Resolve the message with this ID together with its surrounding window |
| attachment_id?2 3 | snowflake | Resolve the message with this attachment together with its surrounding window |
| filename?3 | string | The exact filename of the attachment named by attachment_id (1-255 characters) |
| context_limit?2 | integer | Size of the window returned by a lookup, counting the resolved message (1-100, default 50) |
| limit?1 | integer | Maximum messages to return when searching (1-100, default 25) |
1 Applies to the search mode only. Omitting q searches for the empty string
2 message_id takes precedence over every other member, and attachment_id over q. A lookup ignores limit and a search ignores context_limit
3 Supply both together. Sending attachment_id without filename returns 400 INVALID_FORM_BODY against filename
Search response body
Section titled “Search response body”Returned when neither message_id nor attachment_id was supplied.
| Field | Type | Description |
|---|---|---|
| messages4 | array[Admin message object] | Matching messages (at most 100) |
| message_responses? | array[message object] | The same messages in the public wire shape, same order (at most 100) |
| total5 | integer | The number of matches that still exist |
4 Holds at most limit entries. There is no cursor and no offset member, so this operation returns the first page of matches only
5 Counts every surviving match, so it can exceed the length of messages
Lookup response body
Section titled “Lookup response body”Returned when message_id or attachment_id was supplied. It is the same body Get message returns.
| Field | Type | Description |
|---|---|---|
| messages | array[Admin message object] | The resolved message and its surrounding window, oldest first (at most 100) |
| message_responses? | array[message object] | The same messages in the public wire shape, same order (at most 100) |
| message_id6 | ?snowflake | The ID of the resolved message |
6 Null only for an attachment lookup that matched no attachment, in which case messages is empty too. A message_id lookup echoes the supplied ID even when no such message exists
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | search or lookup response body | Search or lookup completed |
The result is empty for an unknown channel, for a message that does not exist, and for an attachment whose filename does not match. This operation never answers 404.
With no message search service configured the search mode returns an empty messages array and total zero. The lookup modes are unaffected.
Side effects
Section titled “Side effects”One Admin audit entry is recorded with the action search_messages. Its metadata key mode is message for a message_id lookup, attachment for an attachment lookup, and search otherwise, and result_count is the number of messages returned.
- A
message_idlookup has the target typemessageand the message ID as the target. It addschannel_id,context_limit, andfound, which istruewhen the message is inmessages. - An attachment lookup has the target type
channeland the channel ID as the target. It addsattachment_id,context_limit, andfound, which istruewhen the attachment resolved. A resolved attachment also addsmessage_id. - A search has the target type
channeland the channel ID as the target. It addslimitandtotal, andhas_queryastruewhenqis supplied.
The query text and the filename are not recorded. A 400 records nothing.
Rate limit
Section titled “Rate limit”100 requests per minute for each authenticated user, on the shared admin:message:operation bucket.
Get message shred job
Section titled “Get message shred job”GET/v1/admin/messages/shreds/{job_id}Returns one message shred status object. Requires message:shred.
Shred jobs are created by Shred user messages and by the non-dry-run form of Delete all user messages. Both return the identifier this operation reads.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| job_id1 | snowflake | The message shred job ID, taken from the queueing response |
1 A snowflake issued when the job was queued, so a value that is not a decimal integer fails path validation instead of reporting not_found
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | message shred status object | Job state was returned, including not_found for an unknown or expired job |
Side effects
Section titled “Side effects”One Admin audit entry is recorded with the action get_message_shred_status, the target type message_shred, and the target ID 0. Its metadata keys are job_id and status, which is the returned job state.
Rate limit
Section titled “Rate limit”100 requests per minute for each authenticated user, on the shared admin:message:operation bucket.