Skip to content
Fluxer API

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.

Fluxer records the reason a membership exists at the moment it creates that membership. The HTTP API defines no operation that rewrites the value.

ValueNameDescription
0CREATORMember created the guild
1INSTANT_INVITEMember joined through an ordinary invite
2VANITY_URLMember joined through the guild vanity URL
3BOT_INVITEAccount was added through a bot invite
4ADMIN_FORCE_ADDInstance administrator added the member directly
6DISCOVERYMember joined through guild discovery

The value 5 is not assigned.

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.

FieldTypeDescription
id1stringThe identity of the index document, one per membership
guild_idsnowflakeThe ID of the guild the membership belongs to
user_idsnowflakeThe ID of the account the membership belongs to
usernamestringThe username of the account
discriminator2stringThe four-digit discriminator of the account
global_name?stringThe global display name of the account, or null when none is set
nickname3?stringThe nickname of the member in this guild, or null when none is set
role_ids3 4array[snowflake]The IDs of the roles assigned to the member
joined_at5integerThe time at which the account became a member, in Unix seconds
supplemental6guild member search supplemental objectThe join metadata only this search exposes
is_botbooleanWhether 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

{
"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
}

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.

FieldTypeDescription
join_source_type?1 2?integerThe join source type recorded for the membership
source_invite_code1?stringThe invite code the member joined through
inviter_id1?snowflakeThe 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

One search returns this envelope. Every field is always present.

FieldTypeDescription
guild_idsnowflakeThe ID of the guild the search ran against
membersarray[guild member search result object]The matched page in the requested order
page_result_count1integerThe number of results in members
total_result_count2integerThe total number of indexed memberships matching the filters
indexing3booleanWhether 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.

{
"guild_id": "1489002177550843904",
"members": [],
"page_result_count": 0,
"total_result_count": 0,
"indexing": true
}
POST/v1/guilds/{guild_id}/members-searchBot

Searches the guild member index. Returns a guild member search response object on success. Requires membership of the guild.

  • 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_NICKNAMES is 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_PERMISSIONS as 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.

FieldTypeDescription
guild_idsnowflakeThe ID of the guild

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.

FieldTypeDescription
query?1 2stringThe text matched against the indexed identity fields (max 100 characters)
limit?integerThe maximum number of results to return (1-100, default 25)
offset?integerThe number of matching results to skip (minimum 0, default 0)
role_ids?3array[snowflake]The role IDs a matched member must hold (max 10)
joined_at_gte?4integerUnix seconds, includes members who joined at or after this time
joined_at_lte?4integerUnix seconds, includes members who joined at or before this time
join_source_type?5array[integer]The join source types to include (max 10)
source_invite_code?2 5array[string]The invite codes to include (max 10)
is_bot?booleanInclude only bot accounts when true, and only non-bot accounts when false
user_created_at_gte?4 6integerUnix seconds, includes accounts created at or after this time
user_created_at_lte?4 6integerUnix seconds, includes accounts created at or before this time
sort_by?7stringThe sort field, either joinedAt or relevance
sort_order?7stringThe 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.

StatusBodyCondition
200guild member search response objectSearch was evaluated, or the index is not ready
400error responseFilter, sort value, limit, or offset is invalid
4031error responseGuild is unavailable, a body string is blocked, or the caller is not a member or holds none of the required permissions
404error responseGuild 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.

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.

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.