Guild member search
Guild member search finds the members of a guild by name, role, and join information. One route answers it from a search index and returns a guild member search result object for each match.
A guild an operator has marked unavailable returns 403 MISSING_ACCESS before the route runs.
Results are eventually consistent with direct membership reads. Fluxer logs a failed index write and discards it.
Join source types
Section titled “Join source types”Fluxer records the reason a membership exists at the moment it creates that membership. The HTTP API defines no operation that rewrites the value.
| Value | Name | Description |
|---|---|---|
| 0 | CREATOR | Member created the guild |
| 1 | INSTANT_INVITE | Member joined through an ordinary invite |
| 2 | VANITY_URL | Member joined through the guild vanity URL |
| 3 | BOT_INVITE | Account was added through a bot invite |
| 4 | ADMIN_FORCE_ADD | Instance administrator added the member directly |
| 6 | DISCOVERY | Member joined through guild discovery |
The value 5 is not assigned.
Guild member search result object
Section titled “Guild member search result object”A guild member search result is one matched membership as the search index stored it. It flattens the account fields the guild member object nests under user.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| id1 | string | The identity of the index document, one per membership |
| guild_id | snowflake | The ID of the guild the membership belongs to |
| user_id | snowflake | The ID of the account the membership belongs to |
| username | string | The username of the account |
| discriminator2 | string | The four-digit discriminator of the account |
| global_name | ?string | The global display name of the account, or null when none is set |
| nickname3 | ?string | The nickname of the member in this guild, or null when none is set |
| role_ids3 4 | array[snowflake] | The IDs of the roles assigned to the member |
| joined_at5 | integer | The time at which the account became a member, in Unix seconds |
| supplemental6 | guild member search supplemental object | The join metadata only this search exposes |
| is_bot | boolean | Whether the account is a bot |
1 The guild ID and the user ID joined by an underscore, as {guild_id}_{user_id}. No other operation accepts it as an identifier
2 Left-padded with zeroes to four digits
3 The guild member object names these two fields nick and roles, so a client reusing a member renderer must map them
4 The everyone role is never present
5 The same unit as the joined_at_gte and joined_at_lte filters. The guild member object reports the same moment as an ISO 8601 timestamp
6 Always present, with every field inside it null unless the caller holds MANAGE_GUILD
Example
Section titled “Example”{ "id": "1489002177550843904_1489002177550843906", "guild_id": "1489002177550843904", "user_id": "1489002177550843906", "username": "ada", "discriminator": "0042", "global_name": "Ada", "nickname": null, "role_ids": ["1489002177550843910"], "joined_at": 1755158400, "supplemental": {"join_source_type": 1, "source_invite_code": "aBc123", "inviter_id": "1489002177550843905"}, "is_bot": false}Guild member search supplemental object
Section titled “Guild member search supplemental object”A guild member search supplemental object has the join provenance the guild member object never exposes. Only a caller that can already manage the guild reads it.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| join_source_type?1 2 | ?integer | The join source type recorded for the membership |
| source_invite_code1 | ?string | The invite code the member joined through |
| inviter_id1 | ?snowflake | The ID of the account that created the invite the member joined through |
1 Null both when the caller lacks MANAGE_GUILD and when the membership recorded no value, so a null does not distinguish the two
2 Always emitted, so treat an absent field and a null field alike
Guild member search response object
Section titled “Guild member search response object”One search returns this envelope. Every field is always present.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | The ID of the guild the search ran against |
| members | array[guild member search result object] | The matched page in the requested order |
| page_result_count1 | integer | The number of results in members |
| total_result_count2 | integer | The total number of indexed memberships matching the filters |
| indexing3 | boolean | Whether the guild member index is being built |
1 The length of members
2 The matching document count the configured search backend reports
3 A true value always comes with an empty members array and both counts at zero
An Elasticsearch instance reports the true total_result_count. A Meilisearch instance reports an estimate that saturates at 10000. In a very large guild that value can be lower than the true number of matches.
Example
Section titled “Example”{ "guild_id": "1489002177550843904", "members": [], "page_result_count": 0, "total_result_count": 0, "indexing": true}Search guild members
Section titled “Search guild members”POST/v1/guilds/{guild_id}/members-searchSearches the guild member index. Returns a guild member search response object on success. Requires membership of the guild.
Limitations
Section titled “Limitations”- The caller must also hold at least one of MANAGE_GUILD, MANAGE_ROLES, MANAGE_NICKNAMES, BAN_MEMBERS, MODERATE_MEMBERS, or KICK_MEMBERS.
- Five of the six qualifying bits are elevated permissions. In a guild whose MFA level is elevated, a caller other than the guild owner who holds one of those five and has no enrolled authenticator receives 400
TWO_FACTOR_REQUIRED.MANAGE_NICKNAMESis not elevated, so a caller who qualifies through it alone never receives that code. - A non-member of an existing guild receives the same 403
MISSING_PERMISSIONSas a member holding none of the qualifying bits, so a caller cannot tell the two apart.
A guild that does not exist returns 404 UNKNOWN_GUILD.
List guild members needs only membership and returns the complete member object for everyone. The permissions above gate the filtering, the sorting, the deep paging, and the supplemental join provenance.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | The ID of the guild |
JSON body
Section titled “JSON body”Every field is optional, and an omitted filter is not applied. The route reads an omitted, empty, or whitespace-only body as an empty object. A body that is not valid JSON returns 400 INVALID_FORM_BODY with the validation code INVALID_FORMAT at the body path. A request with no usable field returns the first page of every indexed membership.
| Field | Type | Description |
|---|---|---|
| query?1 2 | string | The text matched against the indexed identity fields (max 100 characters) |
| limit? | integer | The maximum number of results to return (1-100, default 25) |
| offset? | integer | The number of matching results to skip (minimum 0, default 0) |
| role_ids?3 | array[snowflake] | The role IDs a matched member must hold (max 10) |
| joined_at_gte?4 | integer | Unix seconds, includes members who joined at or after this time |
| joined_at_lte?4 | integer | Unix seconds, includes members who joined at or before this time |
| join_source_type?5 | array[integer] | The join source types to include (max 10) |
| source_invite_code?2 5 | array[string] | The invite codes to include (max 10) |
| is_bot? | boolean | Include only bot accounts when true, and only non-bot accounts when false |
| user_created_at_gte?4 6 | integer | Unix seconds, includes accounts created at or after this time |
| user_created_at_lte?4 6 | integer | Unix seconds, includes accounts created at or before this time |
| sort_by?7 | string | The sort field, either joinedAt or relevance |
| sort_order?7 | string | The sort direction, either asc or desc |
1 Trimmed before use. An absent or whitespace-only value applies no text clause
2 Scanned by content moderation like any other body string, so a value of at least three characters matching a blocklist returns 403 CONTENT_BLOCKED
3 Every listed role must be held by a result, so several entries narrow the search
4 Both ends are inclusive, and supplying only one leaves the other unbounded
5 Applied only when the caller holds MANAGE_GUILD, and discarded for any other caller. Several entries widen the search
6 Derived from the account’s snowflake
7 The sort field is camel-cased joinedAt, where the result object names the same value joined_at
Input normalisation rewrites "" to null, which this field rejects with 400 INVALID_FORM_BODY. " " is accepted.
With no sort_by, the route sorts by join time and defaults sort_order to desc. Two members with the same join time are ordered by descending id. relevance ignores sort_order. A Meilisearch instance orders relevance by its own ranking rules. An Elasticsearch instance orders relevance by descending id.
Text matching runs over the username, the discriminator, the global display name, the guild nickname, and the user ID, and a query can match the middle of a username as well as its start. Term matching and typo tolerance belong to the search backend. Filter matching is exact in every case.
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | guild member search response object | Search was evaluated, or the index is not ready |
| 400 | error response | Filter, sort value, limit, or offset is invalid |
| 4031 | error response | Guild is unavailable, a body string is blocked, or the caller is not a member or holds none of the required permissions |
| 404 | error response | Guild does not exist and the request returns UNKNOWN_GUILD |
1 The error code is MISSING_ACCESS for an unavailable guild, CONTENT_BLOCKED for a blocked body string, and MISSING_PERMISSIONS otherwise
An index that has never been built, or that predates the instance forced reindex point, returns 200 with an empty page and indexing set to true, and the request schedules the rebuild. The same empty body with indexing false covers a guild whose record disappeared between the membership check and the index read, an instance with no search backend configured, and an instance still initialising. This operation never returns FEATURE_TEMPORARILY_DISABLED.
Side effects
Section titled “Side effects”The route enqueues a rebuild of the guild’s member index when the guild has never been indexed or was last indexed before the instance forced reindex point.
Rate limit
Section titled “Rate limit”40 requests per 10 seconds for each authenticated user and guild ID, on the shared guild:members::guild_id bucket. List guild members, Get current guild member, Get guild member, and List guild bans consume the same bucket.