Discovery
Discovery is the public directory of guilds any account can browse and join. A guild manager applies to have a guild listed, and an operator reviews that application through the Admin Discovery API.
Join discovery guild is user-only and rejects a bot token with 403 ACCESS_DENIED. Every other route accepts a user session token or a bot token.
On a guild an operator has marked unavailable, Fluxer refuses Apply for discovery, Edit discovery application, Withdraw discovery application, and Get discovery status with 403 MISSING_ACCESS before the route runs. The gate does not cover Join discovery guild.
The four routes under /v1/guilds/{guild_id}/discovery require MANAGE_GUILD, which is an elevated permission. While the guild MFA level is elevated, a caller other than the owner also needs an enrolled authenticator, and receives 400 TWO_FACTOR_REQUIRED without one. A guild that does not exist returns 404 UNKNOWN_GUILD. Both a non-member and a member without the permission return 403 MISSING_PERMISSIONS. The routes answer 503 SERVICE_UNAVAILABLE when the check cannot be admitted, and 504 GATEWAY_TIMEOUT when it does not answer in time.
Discovery guild object
Section titled “Discovery guild object”One search result. Every field except the two counts is read from the discovery search index.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| id | snowflake | The ID of the guild |
| name | string | The name of the guild at index time |
| icon3 | ?string | The icon hash of the guild, or null when it stores none |
| banner3 | ?string | The banner hash of the guild, or null when it stores none |
| description1 | ?string | The description supplied on the application, or null |
| category_type1 | integer | The discovery category the listing is filed under |
| primary_language1 | ?string | The supported primary language code of the listing, or null |
| custom_tags1 | array[string] | The normalised custom tags of the listing |
| member_count2 | integer | The current member count of the guild |
| online_count2 | integer | The current online member count of the guild |
| features | array[string] | The guild features the guild has |
| verification_level4 | integer | The effective verification level of the guild |
1 The four listing fields come from the guild’s approved application as it stood at index time, and an entry that stores no category is reported as category 0
2 Refreshed from the main Gateway at response time. When that refresh fails, the operation still succeeds and reports the indexed member count with an online_count of 0
3 An animated hash retains its a_ prefix, which is the animation indicator for this object
4 A listed guild is reported at least at level 1, so a guild that stores level 0 is reported as 1 while it remains discoverable
Example
Section titled “Example”{ "id": "1489002177550843904", "name": "Example guild", "icon": "a_9f1c2d3e4b5a60718293a4b5c6d7e8f9", "banner": null, "description": "A place to talk about the example project.", "category_type": 4, "primary_language": "en-US", "custom_tags": ["open source", "rust"], "member_count": 4120, "online_count": 318, "features": ["DISCOVERABLE"], "verification_level": 1}Discovery search result object
Section titled “Discovery search result object”One page of matching listings, together with the total and the per-category counts.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| guilds | array[discovery guild object] | The matching approved guilds on this page of results |
| total1 | integer | The total number of guilds matching the query |
| category_counts2 | array[discovery category count object] | The match count for each category under the current filters |
1 The count describes the complete match set, so it bounds paging through offset
2 Computed with the category filter removed and every other filter applied, so the counts describe what selecting a different category would return. A category with no match is omitted, and the array is ordered by ascending category
Discovery category count object
Section titled “Discovery category count object”One category and the number of listings it holds under the current filters.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| category_type | integer | The discovery category counted |
| count | integer | The number of matching guilds in that category |
Discovery application object
Section titled “Discovery application object”One guild’s discovery listing and review state. A guild has at most one application. A rejected or removed application remains readable with its outcome and reason until the guild applies again or withdraws it.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | The ID of the guild |
| guild_nsfw_level?1 | ?integer | The NSFW level of the guild |
| status | string | The application status of the listing |
| description | string | The description shown on the listing |
| category_type | integer | The discovery category the listing is filed under |
| primary_language2 | ?string | The supported primary language code of the listing, or null |
| custom_tags | array[string] | The normalised custom tags of the listing |
| applied_at | ISO8601 timestamp | The time at which the application was submitted |
| reviewed_at3 | ?ISO8601 timestamp | The time at which the application was approved or rejected, or null |
| review_reason4 | ?string | The reason recorded with the approval or rejection, or null |
| removed_at5 | ?ISO8601 timestamp | The time at which an approved listing was removed, or null |
| removal_reason5 | ?string | The reason recorded with the removal, or null |
1 No route here populates the field. The guild object has the guild’s NSFW level
2 An application that supplies no language is stored with the default en-US, so the public routes never produce the null form
3 Set at review time. An application approved automatically on submission has its submission time here
4 Always null for an automatic approval
5 Set only when an operator removes an approved listing. A guild that withdraws its own application deletes the record
Example
Section titled “Example”{ "guild_id": "1489002177550843904", "status": "pending", "description": "A place to talk about the example project.", "category_type": 4, "primary_language": "en-US", "custom_tags": ["open source", "rust"], "applied_at": "2026-08-04T11:22:19.000Z", "reviewed_at": null, "review_reason": null, "removed_at": null, "removal_reason": null}Discovery status object
Section titled “Discovery status object”The application state of one guild and its current eligibility to apply.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| application | ?discovery application object | The current application of the guild, or null when it has never applied or has withdrawn |
| eligible1 | boolean | Whether the guild currently satisfies the requirement to apply |
| min_member_count2 | integer | The number of members the instance currently requires |
1 False whenever discovery is disabled for the instance, whatever the guild would otherwise satisfy
2 Read from instance configuration, so it is identical for every guild and defaults to 1
Example
Section titled “Example”{ "application": null, "eligible": true, "min_member_count": 1}Discovery category object
Section titled “Discovery category object”One entry of the fixed category registry, as List discovery categories returns it.
Structure
Section titled “Structure”| Field | Type | Description |
|---|---|---|
| id | integer | The discovery category value |
| name | string | The display name of the category |
Discovery categories
Section titled “Discovery categories”The release fixes the set, so an operator cannot add, rename, or remove a category.
| Value | Name | Display name |
|---|---|---|
| 0 | GAMING | Gaming |
| 1 | MUSIC | Music |
| 2 | ENTERTAINMENT | Entertainment |
| 3 | EDUCATION | Education |
| 4 | SCIENCE_AND_TECHNOLOGY | Science & Technology |
| 5 | CONTENT_CREATOR | Content Creator |
| 6 | ANIME_AND_MANGA | Anime & Manga |
| 7 | MOVIES_AND_TV | Movies & TV |
| 8 | OTHER | Other |
Every category value on the wire is one of these integers.
A value outside 0 through 8 fails body or query validation with the validation code INVALID_FORMAT, so Apply for discovery and Edit discovery application reject it before the listing is stored.
The display names above are the strings List discovery categories returns. They are not localised, so the same ID has the same name for every account.
Discovery application statuses
Section titled “Discovery application statuses”| Value | Description |
|---|---|
| pending | Application has been submitted and awaits an operator decision |
| approved | Guild is listed and has the discoverable feature |
| rejected | Application was refused, and the guild can submit a new one |
| removed | Approved listing was withdrawn by an operator, and the guild can submit a new one |
A guild holding a pending or approved application cannot submit another. A guild whose application is rejected or removed can apply again, and the new submission replaces the previous record entirely.
Supported primary languages
Section titled “Supported primary languages”Fluxer stores one primary language on each listing, drawn from the closed set below. The set is specific to discovery, and the client locale registry does not apply here. An application that supplies no language is stored as en-US.
| Value | Name | Native name |
|---|---|---|
| ar | Arabic | العربية |
| bg | Bulgarian | Български |
| cs | Czech | Čeština |
| da | Danish | Dansk |
| de | German | Deutsch |
| el | Greek | Ελληνικά |
| en-US | English | English |
| es-ES | Spanish (Spain) | Español (España) |
| es-419 | Spanish (Latin America) | Español (Latinoamérica) |
| fi | Finnish | Suomi |
| fr | French | Français |
| he | Hebrew | עברית |
| hi | Hindi | हिन्दी |
| hr | Croatian | Hrvatski |
| hu | Hungarian | Magyar |
| id | Indonesian | Bahasa Indonesia |
| it | Italian | Italiano |
| ja | Japanese | 日本語 |
| ko | Korean | 한국어 |
| lt | Lithuanian | Lietuvių |
| nl | Dutch | Nederlands |
| no | Norwegian | Norsk |
| pl | Polish | Polski |
| pt-BR | Portuguese (Brazil) | Português (Brasil) |
| ro | Romanian | Română |
| ru | Russian | Русский |
| sv-SE | Swedish | Svenska |
| th | Thai | ไทย |
| tr | Turkish | Türkçe |
| uk | Ukrainian | Українська |
| vi | Vietnamese | Tiếng Việt |
| zh-CN | Chinese (Simplified) | 中文 (简体) |
| zh-TW | Chinese (Traditional) | 中文 (繁體) |
Custom tags
Section titled “Custom tags”A listing has up to ten custom tags. Fluxer normalises a tag by trimming it, lowercasing it, and collapsing each run of whitespace to one space. Both the submitted string and its normalised form must be 2 through 30 characters, so a submitted string longer than 30 characters is rejected even when trimming would bring it inside the bound. The normalised form must begin with a letter or digit and otherwise contain only letters, digits, spaces, hyphens, underscores, plus signs, and ampersands.
Duplicate normalised values collapse to the first occurrence. A submitted array longer than ten entries fails body validation. An entry that fails these constraints is rejected against its own index.
Search discovery guilds
Section titled “Search discovery guilds”GET/v1/discovery/guildsSearches the approved discovery listings and returns a discovery search result object.
The caller needs no permission and no relationship to the matched guilds.
Query parameters
Section titled “Query parameters”| Field | Type | Description |
|---|---|---|
| query?1 | string | The free-text query (at most 100 characters) |
| category?2 | integer | The single discovery category results are restricted to (0-8) |
| language?3 | string | The single supported primary language results are restricted to |
| tag?4 | string | The single custom tag results are restricted to (at most 30 characters) |
| sort_by?5 | string | The result ordering, one of member_count, online_count, or relevance |
| limit? | integer | The number of results per page (1-48, default 24) |
| offset? | integer | The number of matches to skip (at least 0, default 0) |
1 An omitted query matches every approved listing, so the operation doubles as a browse of the complete directory
2 A value outside 0 through 8 is rejected by query validation
3 A language outside the supported set is rejected by query validation
4 Trimmed, lowercased, and whitespace-normalised like a custom tag, so equivalent spellings match and a value empty after trimming applies no filter
5 Only member_count selects a distinct ordering. online_count, relevance, and an omitted field all order by relevance. Both orderings are descending
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | discovery search result object | Search completed, possibly with no match |
| 400 | error response | Discovery is disabled for the instance and the request returns DISCOVERY_DISABLED |
| 4031 | error response | Caller presents a bearer credential or a revoked account and the request returns ACCESS_DENIED |
| 403 | error response | The account has an outstanding required action and the request returns ACCOUNT_SUSPICIOUS_ACTIVITY |
| 403 | error response | No search backend is configured for the instance and the request returns FEATURE_TEMPORARILY_DISABLED |
1 Only a bearer credential produces this code. A session, bot, or bearer token that no longer resolves to an account returns 401 UNAUTHORIZED
Rate limit
Section titled “Rate limit”30 requests per 10 seconds for each authenticated user, on the discovery:search bucket, which is not partitioned by query.
List discovery categories
Section titled “List discovery categories”GET/v1/discovery/categoriesReturns an array of every discovery category object in ascending id order, which is also the intended display order. The caller needs no permission.
The route answers even while discovery is disabled for the instance.
A client that wants a translated label supplies its own translation keyed on id, and MUST NOT invent a label for an ID this response does not have.
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | array[discovery category object] | Categories were returned |
| 4031 | error response | Caller presents a bearer credential or a revoked account and the request returns ACCESS_DENIED, or the account has an outstanding required action and the request returns ACCOUNT_SUSPICIOUS_ACTIVITY |
1 Only a bearer credential produces ACCESS_DENIED. A session, bot, or bearer token that no longer resolves to an account returns 401 UNAUTHORIZED
Rate limit
Section titled “Rate limit”60 requests per 10 seconds for each authenticated user, on the discovery:categories bucket.
Join discovery guild
Section titled “Join discovery guild”POST/v1/discovery/guilds/{guild_id}/joinAdmits the authenticated account into an approved discovery guild and returns 204 with an empty body. Emits Guild Create, Guild Member Add, User Settings Update, User Guild Settings Update, and Message Create Gateway events.
The caller needs no invite and no permission.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | The ID of the approved guild to join |
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 204 | empty | Account was admitted, or was already a member of the guild |
| 400 | error response | Discovery is disabled for the instance and the request returns DISCOVERY_DISABLED |
| 400 | error response | The guild has no approved application and the request returns DISCOVERY_NOT_DISCOVERABLE |
| 400 | error response | The caller already holds the maximum number of guilds and the request returns MAX_GUILDS |
| 400 | error response | The guild is full and the request returns MAX_GUILD_MEMBERS |
| 4032 | error response | Caller is a bot, presents a bearer credential, or holds a revoked account and the request returns ACCESS_DENIED |
| 4031 | error response | The account has an outstanding required action and the request returns ACCOUNT_SUSPICIOUS_ACTIVITY |
| 403 | error response | The guild has the invites-disabled feature and the request returns INVITES_DISABLED |
| 403 | error response | The caller is banned from the guild directly or by address and the request returns USER_BANNED_FROM_GUILD or USER_IP_BANNED_FROM_GUILD |
| 404 | error response | The approved application names a guild whose record no longer exists and the request returns UNKNOWN_GUILD |
1 An account whose phone requirement was deferred is re-evaluated against the target guild at join time, so an account that satisfies the standing check can still be refused here
2 Only a bot token or a bearer credential produces this code. A session, bot, or bearer token that no longer resolves to an account returns 401 UNAUTHORIZED
Side effects
Section titled “Side effects”An account that is already a member receives the same 204 response with no Dispatch. Otherwise the operation creates the membership, records discovery as its join source, and adds the guild to the caller’s settings and folder layout.
The joining account’s sessions receive Guild Create. Guild Member Add is dispatched guild-wide and reaches whichever sessions event filtering selects. A bot session always receives it, and a passive user session in a guild with more than 250 members does not receive it until Lazy Request marks that guild active. The joining account receives User Settings Update when the join changes its restricted guild set or its folder layout, and User Guild Settings Update when its account default hides muted channels.
Unless join notifications are suppressed or the guild stores no system channel, the operation creates a USER_JOIN system message in that channel and delivers Message Create. The new member is indexed for Guild member search only in a guild whose member list has already been indexed. No invite use is consumed.
Rate limit
Section titled “Rate limit”10 requests per minute for each authenticated user, on the discovery:join bucket, which is not partitioned by guild.
Apply for discovery
Section titled “Apply for discovery”POST/v1/guilds/{guild_id}/discoverySubmits the discovery listing application of a guild and returns the resulting discovery application object. Requires MANAGE_GUILD. An automatic approval emits a Guild Update Gateway event.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | The ID of the guild |
JSON body
Section titled “JSON body”| Field | Type | Description |
|---|---|---|
| description1 | string | The listing description (10-300 characters) |
| category_type2 | integer | The discovery category to file the listing under (0-8) |
| primary_language?3 | string | The supported primary language code of the listing (default en-US) |
| custom_tags?4 | array[string] | The custom tags to store (at most 10) |
1 Scanned against the instance content blocklists before the guild is read and before the eligibility and duplicate checks run, and a match returns 403 CONTENT_BLOCKED
2 A value outside 0 through 8, a negative value, or a non-integer value is rejected by body validation
3 A code outside the supported set is rejected by body validation, and an omitted field stores en-US
4 Each entry is normalised and validated as described by custom tags, and an omitted field stores an empty array
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | discovery application object | Application was stored as pending, or was approved immediately |
| 400 | error response | Discovery is disabled for the instance and the request returns DISCOVERY_DISABLED, or the guild has fewer members than the instance requires and the request returns DISCOVERY_INSUFFICIENT_MEMBERS |
| 400 | error response | The caller cannot exercise MANAGE_GUILD because of the guild MFA level and the request returns TWO_FACTOR_REQUIRED |
| 4031 | error response | Caller presents a bearer credential or a revoked account and the request returns ACCESS_DENIED |
| 403 | error response | The account has an outstanding required action and the request returns ACCOUNT_SUSPICIOUS_ACTIVITY |
| 403 | error response | The guild is marked unavailable and the request returns MISSING_ACCESS |
| 403 | error response | The description matches a content blocklist and the request returns CONTENT_BLOCKED |
| 403 | error response | The caller lacks MANAGE_GUILD and the request returns MISSING_PERMISSIONS |
| 404 | error response | Guild does not exist and the request returns UNKNOWN_GUILD |
| 409 | error response | The guild already holds a pending or approved application and the request returns DISCOVERY_ALREADY_APPLIED |
1 Only a bearer credential produces this code. A session, bot, or bearer token that no longer resolves to an account returns 401 UNAUTHORIZED
Side effects
Section titled “Side effects”The submitted listing replaces a previous rejected or removed application.
A pending application changes no guild feature, does not appear in search, and emits no Dispatch. An automatic approval adds the discoverable feature, indexes the listing so that Search discovery guilds returns it, and delivers Guild Update to every session that can see the guild.
Rate limit
Section titled “Rate limit”5 requests per minute for each authenticated user and guild ID, on the discovery:apply::guild_id bucket, which is shared with Edit discovery application and Withdraw discovery application.
Edit discovery application
Section titled “Edit discovery application”PATCH/v1/guilds/{guild_id}/discoveryUpdates the stored listing of a guild and returns the updated discovery application object. Requires MANAGE_GUILD. The operation emits no Gateway Dispatch.
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 field preserves the stored value.
| Field | Type | Description |
|---|---|---|
| description?1 | string | The listing description (10-300 characters) |
| category_type?2 | integer | The discovery category to file the listing under (0-8) |
| primary_language?3 | string | The supported primary language code of the listing |
| custom_tags?4 | array[string] | The custom tags to store (at most 10) |
1 A supplied value is scanned against the instance content blocklists before the stored application is read, and a match returns 403 CONTENT_BLOCKED
2 A value outside 0 through 8 is rejected by body validation
3 A supplied code replaces the stored one. A listing always stores a language, so no update clears it
4 A supplied array becomes the complete stored tag list, so an empty array clears every tag
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | discovery application object | Listing was updated, or the submitted values already matched the stored ones |
| 400 | error response | Discovery is disabled for the instance and the request returns DISCOVERY_DISABLED |
| 400 | error response | The caller cannot exercise MANAGE_GUILD because of the guild MFA level and the request returns TWO_FACTOR_REQUIRED |
| 4031 | error response | Caller presents a bearer credential or a revoked account and the request returns ACCESS_DENIED |
| 403 | error response | The account has an outstanding required action and the request returns ACCOUNT_SUSPICIOUS_ACTIVITY |
| 403 | error response | The guild is marked unavailable and the request returns MISSING_ACCESS |
| 403 | error response | The description matches a content blocklist and the request returns CONTENT_BLOCKED |
| 403 | error response | The caller lacks MANAGE_GUILD and the request returns MISSING_PERMISSIONS |
| 404 | error response | Guild does not exist and the request returns UNKNOWN_GUILD |
| 404 | error response | The guild exists but holds no application, and the request returns DISCOVERY_APPLICATION_NOT_FOUND |
| 409 | error response | The stored application is rejected or removed and the request returns DISCOVERY_APPLICATION_ALREADY_REVIEWED |
1 Only a bearer credential produces this code. A session, bot, or bearer token that no longer resolves to an account returns 401 UNAUTHORIZED
Side effects
Section titled “Side effects”The supplied fields update the listing while preserving its status, submission time, review time, and review reason. Editing an approved listing reindexes its result for Search discovery guilds. A pending listing remains absent from search. No guild feature changes.
Rate limit
Section titled “Rate limit”5 requests per minute for each authenticated user and guild ID, on the discovery:apply::guild_id bucket, which is shared with Apply for discovery and Withdraw discovery application.
Withdraw discovery application
Section titled “Withdraw discovery application”DELETE/v1/guilds/{guild_id}/discoveryDeletes the application record of a guild and returns 204 with an empty body. Requires MANAGE_GUILD. Withdrawing an approved listing emits a Guild Update Gateway event.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | The ID of the guild |
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 204 | empty | Application was deleted |
| 400 | error response | Discovery is disabled for the instance and the request returns DISCOVERY_DISABLED |
| 400 | error response | The caller cannot exercise MANAGE_GUILD because of the guild MFA level and the request returns TWO_FACTOR_REQUIRED |
| 4031 | error response | Caller presents a bearer credential or a revoked account and the request returns ACCESS_DENIED |
| 403 | error response | The account has an outstanding required action and the request returns ACCOUNT_SUSPICIOUS_ACTIVITY |
| 403 | error response | The guild is marked unavailable and the request returns MISSING_ACCESS |
| 403 | error response | The caller lacks MANAGE_GUILD and the request returns MISSING_PERMISSIONS |
| 404 | error response | Guild does not exist and the request returns UNKNOWN_GUILD |
| 404 | error response | The guild exists but holds no application, and the request returns DISCOVERY_APPLICATION_NOT_FOUND |
1 Only a bearer credential produces this code. A session, bot, or bearer token that no longer resolves to an account returns 401 UNAUTHORIZED
Side effects
Section titled “Side effects”The application is permanently deleted. Withdrawing an approved listing also removes the discoverable feature, removes the listing from the discovery index, and delivers Guild Update to every session that can see the guild. Withdrawing a pending, rejected, or removed application changes no guild feature and emits no Dispatch. Existing members are unaffected.
Rate limit
Section titled “Rate limit”5 requests per minute for each authenticated user and guild ID, on the discovery:apply::guild_id bucket, which is shared with Apply for discovery and Edit discovery application.
Get discovery status
Section titled “Get discovery status”GET/v1/guilds/{guild_id}/discoveryReturns the discovery status object of one guild, including for a guild that has never applied. Requires MANAGE_GUILD.
The route answers even while discovery is disabled for the instance, reporting eligible as false in that case. It computes eligible from the current member count.
Path parameters
Section titled “Path parameters”| Field | Type | Description |
|---|---|---|
| guild_id | snowflake | The ID of the guild |
Response
Section titled “Response”| Status | Body | Condition |
|---|---|---|
| 200 | discovery status object | Status was returned |
| 400 | error response | The caller cannot exercise MANAGE_GUILD because of the guild MFA level and the request returns TWO_FACTOR_REQUIRED |
| 4031 | error response | Caller presents a bearer credential or a revoked account and the request returns ACCESS_DENIED |
| 403 | error response | The account has an outstanding required action and the request returns ACCOUNT_SUSPICIOUS_ACTIVITY |
| 403 | error response | The guild is marked unavailable and the request returns MISSING_ACCESS |
| 403 | error response | The caller lacks MANAGE_GUILD and the request returns MISSING_PERMISSIONS |
| 404 | error response | Guild does not exist and the request returns UNKNOWN_GUILD |
1 Only a bearer credential produces this code. A session, bot, or bearer token that no longer resolves to an account returns 401 UNAUTHORIZED
Rate limit
Section titled “Rate limit”30 requests per 10 seconds for each authenticated user and guild ID, on the discovery:status::guild_id bucket.