Search
Message search finds indexed messages that match a text query and filters. One request can search a channel, a guild, your direct messages or several of these.
A message matches the text query only when it has every word of it. How words and typos match depends on the instance's search backend (Elasticsearch or Meilisearch), but filters always match exactly.
Message search result object
Section titled “Message search result object”One page of matching messages.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| messages1 | array[message object] | The matching messages on the page |
| channels | array[channel object] | The channels the returned messages belong to |
| total2 | integer | The number of messages matching the query |
| hits_per_page | integer | The page size that was applied |
| page | integer | The page number that was applied |
| cursor? | array[string] | Not used for paging |
| threads?3 | array[thread object] | The threads that contain a returned message |
| members?3 | array[thread member object] | Your thread member object for each of those threads you joined |
1 Messages have no referenced_message field
2 In a channel context without READ_MESSAGE_HISTORY, this is the number of messages in messages
3 Present only when a returned message is in a thread and the request is not a single channel search
Search indexing object
Section titled “Search indexing object”Fluxer returns this object with status 200 when a channel in the search isn't indexed yet or its index is out of date. Fluxer starts indexing it, and you can retry the same request later to get results. Check for indexing to tell this object apart from a result. In the all_guilds, all and open_dms_and_all_guilds scopes, this happens when any guild channel you can read needs indexing, even one you left out of channel_ids.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| indexing | boolean | Always true |
Search scopes
Section titled “Search scopes”| Value | Description |
|---|---|
| current | The guild in context_guild_id, or the channel in context_channel_id when no guild is given |
| open_dms | Your open direct message and group direct message channels |
| all_dms | Every direct message and group direct message channel you are a recipient of |
| all_guilds | Every guild you are a member of |
| all | All guilds plus all_dms |
| open_dms_and_all_guilds | All guilds plus open_dms |
A bot can only use current, and any other value returns 400 INVALID_FORM_BODY with the field code BOT_SEARCH_SCOPE_UNAVAILABLE on scope.
To search members, communities or threads, see Guild member search, Discovery and Search threads.
Search author types
Section titled “Search author types”| Value | Description |
|---|---|
| user | An ordinary user account |
| bot | A bot account |
| webhook | A webhook |
Search content types
Section titled “Search content types”| Value | Description |
|---|---|
| image | Has an attachment with an image/ media type |
| sound | Has an attachment with an audio/ media type |
| video | Has an attachment with a video/ media type |
| file | Has at least one attachment |
| sticker | Has at least one sticker |
| embed | Has at least one preview or rich embed |
| link | Has an HTTP or HTTPS URL in its text |
| poll | Accepted but matches nothing |
| snapshot | Is a forward |
Search embed types
Section titled “Search embed types”| Value | Description |
|---|---|
| image | An image preview embed |
| video | A video preview embed |
| sound | Accepted but matches nothing. Use the sound content type |
| article | An article or webpage preview embed |
Search sort fields
Section titled “Search sort fields”| Value | Description |
|---|---|
| timestamp | Creation time |
| relevance1 | The search backend's own order |
1 sort_order doesn't apply, and on Elasticsearch this is the same as timestamp with desc
Search sort orders
Section titled “Search sort orders”| Value | Description |
|---|---|
| asc | Oldest first |
| desc | Newest first |
Search messages
Section titled “Search messages”POST/v1/search/messagesSearches indexed messages in the resolved scope. Returns a message search result object, or a search indexing object when an index isn't ready.
A guild search only includes channels where you have VIEW_CHANNEL and READ_MESSAGE_HISTORY. To search a single guild channel through context_channel_id, you need VIEW_CHANNEL, and without READ_MESSAGE_HISTORY you only get messages after the guild's history cutoff.
Threads are only searched for bots and for sessions with the channel_threads client capability. The same applies to a thread, forum or media channel in channel_ids.
JSON body
Section titled “JSON body”Every field is optional, but the default current scope needs context_guild_id or context_channel_id. Without either, it returns 400 with the field code CONTEXT_CHANNEL_OR_GUILD_ID_REQUIRED.
| Field | Type | Description |
|---|---|---|
| scope? | string | Search scope (default current) |
| context_channel_id? | snowflake | The ID of the channel to search |
| context_guild_id? | snowflake | The ID of the guild to search |
| channel_ids?1 | array[snowflake] | The channel IDs to narrow the scope to (at most 500) |
| channel_id?1 | array[snowflake] | An alias of channel_ids (at most 500) |
| hits_per_page? | integer | The number of messages on each page (1-25, default 25) |
| page? | integer | The page number (1-400, default 1) |
| cursor? | array[string] | Leave this out. Outside a channel context, a non-empty value returns the first page |
| min_id?2 | snowflake | The lowest message ID to match, exclusive |
| max_id?2 | snowflake | The highest message ID to match, exclusive |
| content?3 | string | The free-text query (1-1024 characters) |
| contents?3 | array[string] | Alternative free-text queries (at most 100, 1-1024 characters each) |
| exact_phrases?4 | array[string] | Phrases that must all match (at most 10, 1-1024 characters each) |
| exclude_channel_id? | array[snowflake] | Channel IDs to exclude (at most 500) |
| author_id? | array[snowflake] | Author user IDs, any of which can match (at most 100) |
| exclude_author_id? | array[snowflake] | Author user IDs to exclude (at most 100) |
| author_type? | array[string] | Author types, any of which can match (at most 20) |
| exclude_author_type? | array[string] | Author types to exclude (at most 20) |
| mentions? | array[snowflake] | User IDs that must all be mentioned (at most 100) |
| exclude_mentions? | array[snowflake] | User IDs, any of which excludes a message (at most 100) |
| mention_everyone? | boolean | Whether a matching message has an everyone mention |
| pinned? | boolean | Whether a matching message is pinned |
| has? | array[string] | Content types that must all be present (at most 20) |
| exclude_has? | array[string] | Content types that can't be present (at most 20) |
| embed_type? | array[string] | Embed types that must all be present (at most 20) |
| exclude_embed_type? | array[string] | Embed types to exclude (at most 20) |
| embed_provider?5 | array[string] | Embed provider names that must all be present (at most 50, 1-256 characters each) |
| exclude_embed_provider?5 | array[string] | Embed provider names to exclude (at most 50, 1-256 characters each) |
| link_hostname?5 | array[string] | Hostnames that must all be present (at most 100, 1-255 characters each) |
| exclude_link_hostname?5 | array[string] | Hostnames to exclude (at most 100, 1-255 characters each) |
| attachment_filename?5 | array[string] | Filenames that must all be present (at most 100, 1-1024 characters each) |
| exclude_attachment_filename?5 | array[string] | Filenames to exclude (at most 100, 1-1024 characters each) |
| attachment_extension?6 | array[string] | Extensions that must all be present (at most 50, 1-32 characters each) |
| exclude_attachment_extension?6 | array[string] | Extensions to exclude (at most 50, 1-32 characters each) |
| sort_by? | string | Search sort field (default timestamp) |
| sort_order? | string | Search sort order (default desc) |
| include_nsfw?7 | boolean | Whether age-restricted channels can give results (default false) |
1 A channel context ignores them
2 On Meilisearch, the comparison uses the second the ID was created in
3 Matches message text and embed text. On Elasticsearch, contents replaces content when both are supplied
4 Terms must appear adjacent and in order
5 Compared exactly and case-sensitively
6 Write extensions in lowercase without the dot. Only the part after the last dot of a filename counts, and only when it has 1-10 characters
7 Ignored unless you are 18 or older. Bots always count as 18 or older
Every channel in channel_ids must be in the scope. A channel from another guild returns 400 with the field code ALL_CHANNELS_MUST_BELONG_TO_GUILD, and any other channel outside the scope returns 403 MISSING_PERMISSIONS.
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | message search result object | search indexing object | The search completed, or an index isn't ready |
| 400 | error response | INVALID_FORM_BODY for a bad scope, a channel from another guild or no context |
| 403 | error response | FEATURE_TEMPORARILY_DISABLED when the instance has no search backend |
| 403 | error response | NSFW_CONTENT_AGE_RESTRICTED when the context is age restricted and you are not old enough |
| 403 | error response | CONTENT_BLOCKED when a search string matches the instance blocklist |
The rate limit is 20 requests per 10 seconds, on the search:messages bucket.