From a3cf960660489d7ef0763d5692e1b4c7fc59068d Mon Sep 17 00:00:00 2001 From: Hampus Date: Sat, 3 Oct 2026 14:48:09 +0200 Subject: [PATCH] docs(discovery): document the channel preview route (#3165) --- .../src/content/docs/http-api/discovery.mdx | 91 ++++++++++++++++++- 1 file changed, 88 insertions(+), 3 deletions(-) diff --git a/fluxer_docs/src/content/docs/http-api/discovery.mdx b/fluxer_docs/src/content/docs/http-api/discovery.mdx index 3923c1ba9..f128b549a 100644 --- a/fluxer_docs/src/content/docs/http-api/discovery.mdx +++ b/fluxer_docs/src/content/docs/http-api/discovery.mdx @@ -8,14 +8,14 @@ import RouteHeader from '@/components/RouteHeader.astro'; 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](/admin-api/discovery/). -[Join discovery guild](#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. Besides that rejection, a bearer credential is the only credential that produces `ACCESS_DENIED` on any route here. Where a response table below pairs a revoked account with `ACCESS_DENIED`, a session, bot, or bearer token that no longer resolves to an account returns 401 `UNAUTHORIZED` instead. +[Preview discovery channel](#preview-discovery-channel) and [Join discovery guild](#join-discovery-guild) are user-only and reject a bot token with 403 `ACCESS_DENIED`. Every other route accepts a user session token or a bot token. Besides that rejection, a bearer credential is the only credential that produces `ACCESS_DENIED` on any route here. Where a response table below pairs a revoked account with `ACCESS_DENIED`, a session, bot, or bearer token that no longer resolves to an account returns 401 `UNAUTHORIZED` instead. -On a guild an operator has marked unavailable, Fluxer refuses [Apply for discovery](#apply-for-discovery), [Edit discovery application](#edit-discovery-application), [Withdraw discovery application](#withdraw-discovery-application), and [Get discovery status](#get-discovery-status) with 403 `MISSING_ACCESS` before the route runs. The gate does not cover [Join discovery guild](#join-discovery-guild). +On a guild an operator has marked unavailable, Fluxer refuses [Apply for discovery](#apply-for-discovery), [Edit discovery application](#edit-discovery-application), [Withdraw discovery application](#withdraw-discovery-application), and [Get discovery status](#get-discovery-status) with 403 `MISSING_ACCESS` before the route runs. The gate does not cover [Preview discovery channel](#preview-discovery-channel) or [Join discovery guild](#join-discovery-guild). The routes under `/v1/guilds/{guild_id}/discovery` require [MANAGE_GUILD](/http-api/permissions/), which is an [elevated permission](/http-api/permissions/#elevated-permissions). While the guild [MFA level](/http-api/guilds/#mfa-levels) 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. :::note[Discovery is an optional instance capability] -Searching, applying, editing, withdrawing, and joining fail with 400 `DISCOVERY_DISABLED` while an operator has it disabled. [List discovery categories](#list-discovery-categories) and [Get discovery status](#get-discovery-status) keep answering. +Searching, previewing a channel, applying, editing, withdrawing, and joining fail with 400 `DISCOVERY_DISABLED` while an operator has it disabled. [List discovery categories](#list-discovery-categories) and [Get discovery status](#get-discovery-status) keep answering. ::: ## Discovery guild object @@ -183,6 +183,54 @@ One entry of the fixed category registry, as [List discovery categories](#list-d | id | integer | The [discovery category](#discovery-categories) value | | name | string | The display name of the category | +## Discovery channel preview object + +The guild and channel behind a channel or message link, as [Preview discovery channel](#preview-discovery-channel) returns them. + +### Structure + +| Field | Type | Description | +| --- | --- | --- | +| guild | [discovery preview guild](#discovery-preview-guild-object) object | The discoverable guild the channel belongs to | +| channel | [discovery preview channel](#discovery-preview-channel-object) object | The channel new members can read | + +### Example + +```json +{ + "guild": { + "id": "1489002177550843904", + "name": "Example guild", + "icon": "a_9f1c2d3e4b5a60718293a4b5c6d7e8f9" + }, + "channel": { + "id": "1489002177550843907", + "name": "general", + "type": 0 + } +} +``` + +## Discovery preview guild object + +### Structure + +| Field | Type | Description | +| --- | --- | --- | +| id | snowflake | The ID of the guild | +| name | string | The current name of the guild | +| icon | ?string | The icon hash of the guild, or null when it stores none | + +## Discovery preview channel object + +### Structure + +| Field | Type | Description | +| --- | --- | --- | +| id | snowflake | The ID of the channel | +| name | ?string | The name of the channel, or null when it stores none | +| type | integer | The [channel type](/http-api/channels/#channel-types) of the channel | + ## Discovery categories The release fixes the set, so an operator cannot add, rename, or remove a category. @@ -324,6 +372,43 @@ A client that wants a translated label supplies its own translation keyed on `id 60 requests per 10 seconds for each authenticated user, on the `discovery:categories` bucket. +## Preview discovery channel + + + +Returns the [discovery channel preview object](#discovery-channel-preview-object) for a channel or message link that points into a discoverable guild, so a client can show the guild and channel before the account joins. The caller needs no permission and no membership. + +The route answers only when the guild holds an approved discovery application, the guild does not have the invites-disabled feature, the channel belongs to that guild, and the `@everyone` role can read the channel. Reading means `@everyone` holds both [VIEW_CHANNEL](/http-api/permissions/) and [READ_MESSAGE_HISTORY](/http-api/permissions/) after the channel's `@everyone` overwrite is applied. A guild whose `@everyone` role has [ADMINISTRATOR](/http-api/permissions/) passes regardless of overwrites. Role and member overwrites are not considered, and any channel type can pass. + +:::note[Every refusal returns the same error] +A guild that does not exist, a guild without an approved listing, a channel that does not exist, a channel in another guild, and a channel `@everyone` cannot read all return 400 `DISCOVERY_NOT_DISCOVERABLE`. The response does not reveal which condition failed. +::: + +### Path parameters + +| Field | Type | Description | +| --- | --- | --- | +| guild_id | snowflake | The ID of the discoverable guild | +| channel_id | snowflake | The ID of the channel to preview | + +### Response + +| Status | Body | Condition | +| --- | --- | --- | +| 200 | [discovery channel preview](#discovery-channel-preview-object) object | Guild is listed in discovery and new members can read the channel | +| 400 | [error response](/http-api/#error-response) | A path parameter is not a valid snowflake and the request returns `INVALID_FORM_BODY` | +| 400 | [error response](/http-api/#error-response) | Discovery is disabled for the instance and the request returns `DISCOVERY_DISABLED` | +| 400 | [error response](/http-api/#error-response) | The guild is not discoverable or `@everyone` cannot read the channel, and the request returns `DISCOVERY_NOT_DISCOVERABLE` | +| 403 | [error response](/http-api/#error-response) | Caller is a bot, presents a bearer credential, or holds a revoked account and the request returns `ACCESS_DENIED` | + +### Side effects + +None. The route reads stored records only and emits no Gateway Dispatch. + +### Rate limit + +60 requests per 10 seconds for each authenticated user, on the `discovery:channel_preview` bucket, which is not partitioned by guild or channel. + ## Join discovery guild