diff --git a/discord/developers/docs/activities/how-activities-work.md b/discord/developers/docs/activities/how-activities-work.md
deleted file mode 100644
index 3edc4a9227..0000000000
--- a/discord/developers/docs/activities/how-activities-work.md
+++ /dev/null
@@ -1,68 +0,0 @@
----
-title: How Activities Work
-description: An introduction to how Activities work on Discord.
----
-
-Activities are web applications that run in an iframe within Discord on desktop, mobile and web. In order to achieve this, we use the [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) protocol to enable secure communication between your application and Discord.
-
-The [Embedded App SDK](https://github.com/discord/embedded-app-sdk) simplifies this process by managing the `postMessage` protocol on your behalf. For details on available commands and their usage, consult the [SDK Reference](/developers/docs/developer-tools/embedded-app-sdk). Our [Sample Projects](/developers/docs/activities/overview#sample-projects) provide practical examples of how to implement these features.
-
-## Designed for Single-Page Apps (SPAs)
-
-This SDK is intended for use by a single-page application. We recognize developers may be using frameworks or approaches that are not an exact fit for single-page applications. We recommend nesting those frameworks inside your Activity's top-level single-page application and passing messages as you see fit. Please refer to the [Nested Messages App](/developers/docs/activities/overview#sample-projects) sample project for guidance on this approach.
-
-## Activity Lifecycle
-
-1. **Initialization:** When your iframe is loaded within Discord, it will include unique query parameters in its URL. These parameters are identifiable by your application using the Discord SDK.
-2. **Handshake Process:** Constructing the SDK instance begins a handshake process with the Discord client. Once the connection is established, the iframe receives a `[FRAME, {evt: 'READY', ...}]` message. The `ready()` method of the SDK instance resolves once a successful connection has been established.
-3. **Authorization and Authentication:** After receiving the `READY` payload, your application should perform authorization and authentication to acquire necessary permissions (scopes). This step is crucial for utilizing specific features or scopes, such as `rpc.activities.write`.
-4. **Interacting with Discord Client:** Post-authentication, your application can subscribe to events and send commands to the Discord client. Note that attempting to use commands or subscribe to events outside your granted scope will result in errors. Adding new scopes may prompt an OAuth modal for user permission re-confirmation.
-5. **Disconnection and Errors:** Receiving a `[CLOSE, {message: string, code: number}]` message indicates an error or a need to restart the connection process.
-6. **Sending Errors or Close Requests:** To communicate an error or request a close from the Discord client, send `[CLOSE, {message?: string, code: number}]`. A code other than CLOSE_NORMAL will display the message to the user, while CLOSE_NORMAL results in a silent closure.
-
-## Sample Code and Activity Lifecycle Diagram
-
-
-Below is a minimal example of setting up the SDK. Please see our [Sample Projects](/developers/docs/activities/overview#sample-projects) for more complete sample applications.
-
-
-
-```javascript
-import {DiscordSDK} from '@discord/embedded-app-sdk';
-const discordSdk = new DiscordSDK(YOUR_OAUTH2_CLIENT_ID);
-
-async function setup() {
- // Wait for READY payload from the discord client
- await discordSdk.ready();
-
- // Pop open the OAuth permission modal and request for access to scopes listed in scope array below
- const {code} = await discordSdk.commands.authorize({
- client_id: YOUR_OAUTH2_CLIENT_ID,
- response_type: 'code',
- state: '',
- prompt: 'none',
- scope: ['identify'],
- });
-
- // Retrieve an access_token from your application's server
- const response = await fetch('/api/token', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- code,
- }),
- });
- const {access_token} = await response.json();
-
- // Authenticate with Discord client (using the access_token)
- auth = await discordSdk.commands.authenticate({
- access_token,
- });
-}
-```
-
-This diagram illustrates the communication flow between your application and Discord in the sample code above.
-
-
diff --git a/discord/developers/docs/discovery/best-practices.md b/discord/developers/docs/discovery/best-practices.md
deleted file mode 100644
index 200098dd36..0000000000
--- a/discord/developers/docs/discovery/best-practices.md
+++ /dev/null
@@ -1,105 +0,0 @@
----
-sidebar_label: Best Practices
----
-
-# Discovery Best Practices
-
-So you’ve made an app on Discord and are ready to opt in to discovery on the App Directory! Or maybe you have already listed your app but aren’t seeing as much traction to it as you’d like? Whatever stage you’re at, this guide has some tips and tricks from your friendly Discord Staff members to help boost performance of your App Directory Product Page.
-
-
-This guide references settings and information you can set up and modify within your [app's settings](https://discord.com/developers/applications). If you don't have an app yet, you can follow the [Getting Started guide](/developers/docs/quick-start/getting-started).
-
-
-## The Elevator Pitch
-
-### Quickly tell your users what your app does
-
-App descriptions should convey the value of your app and what it does. Make your app descriptions punchy and to the point - letting folks know what your app does in simple terms while also exciting the potential user to add the app and start using it.
-
-
-
-Be sure to spell check and review your grammar before posting your descriptions. Your app has the potential to be seen by millions of people!
-
-
-
-There are a few places where you can define different descriptions of your app within your [app's settings](https://discord.com/developers/applications).
-
-#### App General Information Description
-
-On the **General Information** tab, there is a general **Description** field (max of 400 characters) that appears within your bot user's profile. When a new user clicks on your app within Discord, they'll see this description.
-
-
-
-#### App Summary
-
-On the **App Directory** tab, the **Summary** field is a short description (max of 200 characters) that users will see when you appear within search results on the App Directory.
-
-When writing your app's Summary, think about how to grab the user's attention and quickly convey the value of your app. Consider the following description:
-
-
-
-While this could be true, it doesn’t really tell folks how the app makes servers better or more fun. The best descriptions start with an attention grabbing sentence that describes a problem a user might want to solve:
-
-
-
-#### App Expanded Description
-
-On the **App Directory** tab, there is an **Expanded Description** field near the bottom of the page. This description appears when someone clicks on your app and enters its profile within the App Directory. This is your opportunity to showcase why a user should install your app, and the best functionality your app has to offer. The description also supports formatting via markdown.
-
-When writing your app's Expanded Description, the first thing you do should be to convey the value of the app to users. After the value is clear, continue on with how to get started with your app after it’s installed.
-
-## Show Your Story
-
-### Include as many relevant visuals as possible
-
-#### Show Your App's Functionality
-
-Add images and gifs to your Product Page and give users a better idea of the amazing functionality of your app. You can start by showing off some of the commands you mentioned in your description and how they work in Discord. What are some of your app’s most popular commands? How do existing users generally interact with your app? The answers to these questions make a great starting point for images on your Product Page.
-
-Additionally, new users need to know what to expect when they install the app so great images should showcase your app in action within a Discord server. The more your images display what your app does and how it appears in Discord, the better.
-
-#### Include Your App's Lore
-
-Other images you may want to include are ones related to your app’s lore (if any). For example, say there was a “Hypesquad App,” I would include the Hypesquad badges and what each of them means (I’m personally Hypesquad balance myself).
-
-#### Add a Video
-
-After adding some images, make a quick screen recording to demonstrate your app’s functionality. Videos are awesome but it's definitely helpful to include images as well, especially for folks who may not watch the entire video.
-
-## Find Your Users
-
-### Utilize search to your advantage
-
-Think of up to five words that describe your app and add them as tags (see image below for an example). Consider what categories your app would fit under or keywords users would type into the search bar when looking for apps to add to their servers.
-
-
-
-## Support Your Users
-
-### Engage with your users directly
-
-Your app’s support server is a paramount part of your App Product Page. It’s important to ensure your app has a dedicated server and channel for communication between your app’s users and its developers and maintainers.
-
-
-
-If your support server isn't [discoverable](https://support.discord.com/hc/en-us/articles/360030843331-Enabling-Server-Discovery), be sure to include an invite link in the "links" section of your App Directory Product Page.
-
-
-
-Some ways you can successfully use your support server includes:
-
-- Encourage users to share feedback or their experience with your app.
-- Offer technical support for users of your app.
-- Share app updates in your support server and update your App’s Product Page description if it changes the functionality of your app.
-
-For general best practices on how to run a server, check out our [Community page](https://discord.com/community).
-
-## General Housekeeping
-
-### Final checks to make sure you’re ready to go
-
-Before you can click the final “Enable Discovery” button, ensure that your App Directory Product Page complies with the rest of Discord’s Directory eligibility criteria, [app content requirements](https://support-dev.discord.com/hc/en-us/articles/9489299950487-App-Directory-App-Content-Requirements-Policy) and Developer [Terms of Service](https://support-dev.discord.com/hc/en-us/articles/8562894815383) and [Policy](https://support-dev.discord.com/hc/en-us/articles/8563934450327).
-
-For more details about what this information entails, read our [Help Center article on Profile Pages](https://support-dev.discord.com/hc/en-us/articles/6378525413143-App-Directory-App-profile-pages).
-
-Now you're ready to publish your new App Directory profile and watch your app grow! If you haven’t already, join our official [Discord Developers server](https://discord.gg/discord-developers) to receive more information on how to update your apps. Way to go, Discord Developer!
diff --git a/discord/developers/docs/monetization/implementing-one-time-purchases.md b/discord/developers/docs/monetization/implementing-one-time-purchases.md
deleted file mode 100644
index 9c08c49410..0000000000
--- a/discord/developers/docs/monetization/implementing-one-time-purchases.md
+++ /dev/null
@@ -1,130 +0,0 @@
-# Implementing One-Time Purchases
-
-One-time purchases enable you to charge your users for premium functionality with in-app items.
-
-- Before you can add one-time purchases to your app, you must [Enable Monetization](/developers/docs/monetization/enabling-monetization) for your app.
-- Once you've confirmed eligibility for your app and team, you will be able to set up a [SKU](/developers/docs/resources/sku) (stock-keeping unit) to represent your one-time purchases.
-
----
-
-## Types of One-Time Purchases
-
-When creating items for one-time purchase, you can choose between durable and consumable items:
-
-- **Durable Items**: A one-time purchase that is permanent and is not subject to either renewal or consumption, such as lifetime access to an app's premium features.
-- **Consumable Items**: A one-time, non-renewable purchase that provides access, such as a temporary power-up or boost in a game.
-
----
-
-## How One-Time Purchases Work
-
-#### For Durable SKUs
-- When a user purchases your durable SKU, Discord creates an [Entitlement](/developers/docs/resources/entitlement) for the purchasing user and that specific [SKU](/developers/docs/resources/sku).
-- You will receive an `ENTITLEMENT_CREATE` event via the Gateway.
-- This entitlement is now available via the `LIST Entitlements` API endpoint.
-- This entitlement will be available on `Interaction Payloads` initiated from the entitled user.
-
-#### For Consumable SKUs
-- When a user purchases your consumable SKU, Discord creates an [Entitlement](/developers/docs/resources/entitlement) for the purchasing user and that specific SKU.
-- You will receive an `ENTITLEMENT_CREATE` event via the Gateway.
-- This entitlement is now available via the `LIST Entitlements` API endpoint.
-- This entitlement will be available on `Interaction Payloads` initiated from the entitled user or users in a guild (for guild subscriptions).
-- Users cannot repurchase this SKU until you consume the entitlement using the [Consume Entitlement API](/developers/docs/resources/entitlement#consume-an-entitlement) endpoint.
- - In [Test Mode](/developers/docs/monetization/implementing-one-time-purchases#using-application-test-mode), repeated purchases are permitted without consumption for developer convenience.
-- When you receive an `ENTITLEMENT_CREATE` event for a consumable SKU, you should process the item purchase in your app and consume the entitlement as soon as possible.
-
----
-
-## Working with Entitlements
-
-When a user purchases a one-time purchase SKU, an entitlement is created. [Entitlements](/developers/docs/resources/entitlement) represent the user's access to your consumable or durable item.
-
-Depending on your app's features, you can use a combination of [Gateway events](/developers/docs/events/gateway-events#entitlements), the [Entitlement HTTP API](/developers/docs/resources/entitlement), and [interaction payloads](/developers/docs/interactions/receiving-and-responding) to keep track of entitlements to users who have purchased items in your app.
-
-### Accessing Entitlements with Gateway Events
-
-When a user purchases a SKU, Discord will emit an [`ENTITLEMENT_CREATE`](/developers/docs/events/gateway-events#entitlements) event. This event will contain the entitlement object that represents the user's access to the SKU. You can use this event to keep track of the user's entitlements in near-time. For One-Time Purchases, you may also receive an `ENTITLEMENT_DELETE` event if the user's entitlement is revoked.
-
-### Accessing Entitlements with the HTTP API
-
-Entitlements are available via the [List Entitlements](/developers/docs/resources/entitlement#list-entitlements) endpoint. You can filter entitlements by a specific user or set of SKUs by using the `?user_id=XYZ` or `?sku_ids=XYZ` query parameters.
-
-### Accessing Entitlements on Interaction Payloads
-
-Entitlements are also available on the `Interaction Payload` when a user interacts with your app. You can find the entitlements on the `entitlements` field of the `Interaction Payload` when [receiving and responding to interactions](/developers/docs/interactions/receiving-and-responding).
-
-### Accessing Entitlements with the Embedded App SDK
-
-When using the [Embedded App SDK](/developers/docs/developer-tools/embedded-app-sdk) to build an [Activity](/developers/docs/activities/overview), you can also [access a user's entitlements](/developers/docs/developer-tools/embedded-app-sdk#getentitlements). Check out the [Implementing In-App Purchases for Activities](/developers/docs/monetization/implementing-iap-for-activities) guide to learn more about monetization with the Embedded App SDK.
-
-Depending on your app's needs, you can use a combination of these methods to keep track of user entitlements.
-
----
-
-## One-Time Purchase Considerations
-
-When implementing one-time purchases, you should consider the following:
-
-### For Durable One-Time Purchases
-
-When offering durable items, users will have access to the SKU indefinitely. Durable items can't be consumed, so you don't need to worry about the user losing access to the item except in the case of a refund.
-
-### For Consumable One-Time Purchases
-When offering consumable items, users can only have one unconsumed entitlement at a time. To handle consumable items in your app or game, you should process and store the consumable item in your app and then make a call to the [Consume Entitlement](/developers/docs/resources/entitlement#consume-an-entitlement) endpoint so that the user can purchase more of this item in the future.
-
-Consuming the entitlement will update the entitlement to return a true value in the entitlement's `consumed` field. You will need to think through how your app keeps track of consumable items to decide on the best strategy for when to consume these entitlements and store the state of the consumable item and quantity in your app.
-
----
-
-## Prompting Users to Purchase an Item
-
-### Responding with a Premium Button
-
-[Responding with a premium button](/developers/docs/monetization/managing-skus#responding-with-a-premium-button) gives you the ability to prompt users to subscribe to your app when they attempt to use a premium feature without a subscription.
-
-You can do this by sending a message with a [button](/developers/docs/components/reference#button) with a [premium style](/developers/docs/components/reference#button-button-styles) and a `sku_id` that allows the user to upgrade to your premium offering.
-
-### Starting a Purchase from an Activity
-
-If you are using the [Embedded App SDK](/developers/docs/developer-tools/embedded-app-sdk) to build an [Activity](/developers/docs/activities/overview), you can also launch the purchase flow for a specific SKU using the SDK. Check out the [Implementing In-App Purchases for Activities](/developers/docs/monetization/implementing-iap-for-activities) guide to learn more about monetization with the Embedded App SDK.
-
----
-
-## Testing Your One-Time Purchase Implementation
-
-
-
-The method of testing purchases for One-Time Purchases differs from the method for App Subscriptions. **Do NOT use Test Entitlements for One-Time Purchases.**
-
-
-
-### Using Application Test Mode
-
-While in Application Test Mode, you can freely make "purchases" of One-Time Purchase SKUs tied to your application. That means you can test buying your consumable and durable items by going through the In-App Purchase flow without any credit card charges.
-
-
-
-You still need to have a valid payment method on file to "purchase" SKUs in Application Test Mode. It just won't be charged at checkout.
-
-
-
-To enable it, first, make sure you have a payment method on file in `User Settings -> Billing` and then:
-
-1. Open up the Discord app
-2. Click on the Settings cog in the bottom left corner
-3. Go to the `Advanced` page under App Settings
-4. Toggle "Developer Mode" **on** and "Application Test Mode" **on**, and enter your application ID. You can leave the other settings as-is.
-5. Exit user settings
-
-Once you enabled Application Test Mode successfully, you should see an orange bar across the top of your screen with the name of your app.
-
-You can now navigate to your Store page and purchase your one-time purchase items without being charged.
-
-The entitlements tied to items purchased in Application Test Mode can be identified by entitlements with a `type` value of 4 to represent `TEST_MODE_PURCHASE`.
-
-
-
-The "Go To SKU" button does not currently work. To purchase your SKU in test mode, go to your Store page.
-
-
-
diff --git a/discord/developers/docs/rich-presence/best-practices.md b/discord/developers/docs/rich-presence/best-practices.md
deleted file mode 100644
index 86d5c138d6..0000000000
--- a/discord/developers/docs/rich-presence/best-practices.md
+++ /dev/null
@@ -1,97 +0,0 @@
----
-sidebar_label: Best Practices
----
-
-# Best Practices for Rich Presence
-
-Rich Presence lets you display actionable data in a Discord user's profile about what they're up to in your game or app. This guide is intended to show some best practices on how to make that data the best it can be.
-
-If you don't already know about Rich Presence, read [the overview](/developers/docs/rich-presence/overview) first.
-
-## How should you think about the data you show?
-
-The data in your players’ profiles is the first thing that others on Discord will see about your game or app, both those familiar with it and those who have never seen it before. It should answer whether someone can play with their friend right now and show data like:
-
-- What the player is currently doing
-- How much time has elapsed or remains (if applicable)
-- Their party state
-- Your cool artwork!
-
-## Tips
-
-### Keep it Short
-
-- `details` and `state` should be snippets of data, not sentences.
-- Make sure your strings stay on one line—especially on the small profile!
-
-###### Examples
-
-
-
-### Make it Actionable!
-
-- Always keep party size data up to date.
-- Keep accurate track of party state: In Queue, In Game, In Menus, etc.
-- Include game modes, ranked vs. unranked, etc. so others can clearly see.
-
-###### Examples
-
-
-
-### Use ALL of the fields (where applicable)!
-
-- Make use of all the fields that are applicable to you.
-- Save space by putting map and character names in the tooltips.
-- Try not to repeat information.
-
-###### Examples
-
-
-
-### Have interesting, expressive art!
-
-- The large image should be consistent for all players in a party.
-- The small image is where you can customize on a per-player basis.
-- Use high resolution artwork so your art looks great on fancy, high DPI screens.
-- We strongly recommend image sizes of 1024x1024 pixels.
-
-###### Examples
-
-
-
-## Launch Checklist
-
-Ready to launch a Rich Presence integration for your game? If so, we recommend looking over this checklist one last time to ensure that your integration is as great as it can be!
-
-#### Profile Strings
-
-- Have you made use of all available fields where appropriate?
-- Do your strings fit on their own lines without line wrapping?
- - Did you check on the smaller profile pop out?
-- Do they clearly communicate:
- - What the player is currently doing?
- - If the player is in a group or playing alone?
- - If the player is in a state where they can party up?
-
-#### Artwork
-
-- Is your artwork high resolution?
-- Are your images at least 1024x1024 pixels?
-- Is it clean, interesting, and descriptive without being too highly detailed?
-- Do you have artwork for every different state? Don't forget your default state/main menu!
-- Did you make use of tooltips and the small image where appropriate?
-
-#### Joining
-
-
-Since all Activities presence data has an **Ask to Join** button, Join Invites are only applicable when building with the [Game SDK](/developers/docs/rich-presence/using-with-the-game-sdk)
-
-
-- Have you successfully implemented join invites for your game if applicable?
-- Does the state of the invite properly represent the party/group in-game with regards to:
- - Size?
- - Open slots?
- - Discord _and_ non-Discord users in the party?
-- Are you able to post invites to Discord without any additional in-game setup or configuration?
-- Are you properly removing data from the presence payload when someone can no longer send invites?
- - A Join secret should not be sent if the player can't invite anyone!
diff --git a/discord/developers/docs/topics/certified-devices.md b/discord/developers/docs/topics/certified-devices.md
deleted file mode 100644
index 69888c2c58..0000000000
--- a/discord/developers/docs/topics/certified-devices.md
+++ /dev/null
@@ -1,203 +0,0 @@
-# Certified Devices
-
-Baked into Discord is the ability for hardware manufacturers to tell us a little more about the certified devices that are plugged into a user's computer. Unfortunately, no, you can't show that a user's PUBG Chicken Dinner was all thanks to the amazing TotallyRealHardware RGB Mouse and Keyboard Set Extraordinaire™, but you _can_ give them an amazing experience using your hardware with Discord!
-
-## How's it work?
-
-I'm glad you asked!
-
-1. [Create an application](https://discord.com/developers/applications) for your hardware vendor—save the Client ID!
-2. Talk to Discord via one simple HTTP or WebSocket call
-3. Send us a [`SET_CERTIFIED_DEVICES`](/developers/docs/topics/rpc#setcertifieddevices) WebSocket payload or equivalent HTTP POST whenever the state of the device changes
-
-Yup, that's it. You give us the real-time info about any connected devices, and we'll handle the rest to make sure that anyone using your device will have an awesome experience. Your device will also have a `CERTIFIED` badge in Discord's audio settings, and really, who doesn't love badges?
-
-
-
-## Connecting
-
-###### Query String Params
-
-| Name | Value | Required |
-|-----------|----------------------|-----------|
-| v | `1` | All |
-| client_id | your app's client id | All |
-| encoding | `json` | WebSocket |
-
-You can send event updates to the following URIs:
-
-###### HTTP
-
-```
-http://127.0.0.1:PORT/rpc?v=1&client_id=YOUR_CLIENT_ID
-```
-
-###### WebSocket
-
-```
-ws://127.0.0.1:PORT?v=1&client_id=YOUR_CLIENT_ID&encoding=json
-```
-
-`PORT` is a range of ports from `6463` to `6473`. You should iterate over these ports with your request until one returns a success response code or succeeds with a socket connection. Keep track of that port number for the rest of the session.
-
-To keep your hardware in sync with Discord, send updates any time the hardware mute is toggled, or one of the voice features like echo cancellation is enabled or disabled by the user. This lets Discord get out of the way of your optimization when you're in control, or help out when you're not, ensuring an awesome experience for anyone using your hardware.
-
-Each time you update, send a full array of `devices`, sorted by your preferred priority. That means if you want a specific headset to be the default that Discord will attempt to use, put it first in the array.
-
-## Getting Device UUID
-
-For each device in the `SET_CERTIFIED_DEVICES` payload, there is an `id` field. This `id` should be the Windows device's UUID, retrieved through the native Windows API. You'll get back something that looks like `{0.0.1.00000000}.{6cff2b76-44a8-46b9-b528-262ad8609d9f}`.
-
-
-
-On macOS, the `id` will be the name of the device.
-
-
-
-###### Microphone Id Example
-
-```cpp
-id = waveInMessage((HWAVEIN)IntToPtr(index),
- DRV_QUERYFUNCTIONINSTANCEID,
- (DWORD_PTR)pstrEndpointId,
- cbEndpointId);
-```
-
-###### Speaker Id Example
-
-```cpp
-id = waveOutMessage((HWAVEIN)IntToPtr(index),
- DRV_QUERYFUNCTIONINSTANCEID,
- (DWORD_PTR)pstrEndpointId,
- cbEndpointId);
-```
-
-## HTTP Example
-
-###### HTTP Request Example
-
-```
-curl -X POST -H 'Content-Type: application/json' -d '
-{
- "nonce": "9b4e9711-97f3-4f35-b047-32c82a51978e",
- "cmd": "SET_CERTIFIED_DEVICES",
- "args": {
- "devices": [
- {
- "type": "audioinput",
- "id": "{0.0.1.00000000}.{6cff2b76-44a8-46b9-b528-262ad8609d9f}",
- "vendor": {
- "name": "SteelSeries",
- "url": "https://steelseries.com"
- },
- "model": {
- "name": "Arctis 7",
- "url": "https://steelseries.com/gaming-headsets/arctis-7"
- },
- "related": ["{0.0.1.00000000}.{6cff2b76-44a8-46b9-b528-262ad8609d9f}"],
- "echo_cancellation": true,
- "noise_suppression": true,
- "automatic_gain_control": true,
- "hardware_mute": false
- }
- ]
- }
-}
-' http://127.0.0.1:PORT/rpc?v=1&client_id=YOUR_CLIENT_ID
-```
-
-The socket will respond with a `200 OK` status code and the following JSON.
-
-###### HTTP Response Example
-
-```json
-{
- "cmd": "SET_CERTIFIED_DEVICES",
- "data": null,
- "evt": null,
- "nonce": "9b4e9711-97f3-4f35-b047-32c82a51978e"
-}
-```
-
-## WebSocket Example
-
-###### RPC Command Example
-
-```json
-{
- "nonce": "9b4e9711-97f3-4f35-b047-32c82a51978e",
- "cmd": "SET_CERTIFIED_DEVICES",
- "args": {
- "devices": [
- {
- "type": "audioinput",
- "id": "{0.0.1.00000000}.{6cff2b76-44a8-46b9-b528-262ad8609d9f}",
- "vendor": {
- "name": "SteelSeries",
- "url": "https://steelseries.com"
- },
- "model": {
- "name": "Arctis 7",
- "url": "https://steelseries.com/gaming-headsets/arctis-7"
- },
- "related": ["{0.0.1.00000000}.{6cff2b76-44a8-46b9-b528-262ad8609d9f}"],
- "echo_cancellation": true,
- "noise_suppression": true,
- "automatic_gain_control": true,
- "hardware_mute": false
- }
- ]
- }
-}
-```
-
-###### RPC Response Example
-
-```json
-{
- "nonce": "9b4e9711-97f3-4f35-b047-32c82a51978e",
- "cmd": "SET_CERTIFIED_DEVICES",
- "data": null,
- "evt": null
-}
-```
-
-## Models
-
-###### Device Object
-
-| Field | Type | Description |
-|---------------------------|---------------------------------------------------------------------------------|----------------------------------------------------------|
-| type | [device type](/developers/docs/topics/certified-devices#models-device-type) | the type of device |
-| id | string | the device's Windows UUID |
-| vendor | [vendor](/developers/docs/topics/certified-devices#models-vendor-object) object | the hardware vendor |
-| model | [model](/developers/docs/topics/certified-devices#models-model-object) object | the model of the product |
-| related | array of strings | UUIDs of related devices |
-| echo_cancellation?\* | boolean | if the device's native echo cancellation is enabled |
-| noise_suppression?\* | boolean | if the device's native noise suppression is enabled |
-| automatic_gain_control?\* | boolean | if the device's native automatic gain control is enabled |
-| hardware_mute?\* | boolean | if the device is hardware muted |
-
-\*These fields are only applicable for `AUDIO_INPUT` device types
-
-###### Vendor Object
-
-| Field | Type | Description |
-|-------|--------|--------------------|
-| name | string | name of the vendor |
-| url | string | url for the vendor |
-
-###### Model Object
-
-| Field | Type | Description |
-|-------|--------|-------------------|
-| name | string | name of the model |
-| url | string | url for the model |
-
-###### Device Type
-
-| Type | Value |
-|--------------|---------------|
-| AUDIO_INPUT | "audioinput" |
-| AUDIO_OUTPUT | "audiooutput" |
-| VIDEO_INPUT | "videoinput" |
diff --git a/discord/developers/docs/topics/opcodes-and-status-codes.md b/discord/developers/docs/topics/opcodes-and-status-codes.md
deleted file mode 100644
index 81987ea785..0000000000
--- a/discord/developers/docs/topics/opcodes-and-status-codes.md
+++ /dev/null
@@ -1,396 +0,0 @@
-# Opcodes and Status Codes
-
-## Gateway
-
-All gateway events in Discord are tagged with an opcode that denotes the payload type. Your connection to our gateway may also sometimes close. When it does, you will receive a close code that tells you what happened.
-
-###### Gateway Opcodes
-
-| Code | Name | Client Action | Description |
-|------|---------------------------|---------------|-----------------------------------------------------------------------------------------|
-| 0 | Dispatch | Receive | An event was dispatched. |
-| 1 | Heartbeat | Send/Receive | Fired periodically by the client to keep the connection alive. |
-| 2 | Identify | Send | Starts a new session during the initial handshake. |
-| 3 | Presence Update | Send | Update the client's presence. |
-| 4 | Voice State Update | Send | Used to join/leave or move between voice channels. |
-| 6 | Resume | Send | Resume a previous session that was disconnected. |
-| 7 | Reconnect | Receive | You should attempt to reconnect and resume immediately. |
-| 8 | Request Guild Members | Send | Request information about offline guild members in a large guild. |
-| 9 | Invalid Session | Receive | The session has been invalidated. You should reconnect and identify/resume accordingly. |
-| 10 | Hello | Receive | Sent immediately after connecting, contains the `heartbeat_interval` to use. |
-| 11 | Heartbeat ACK | Receive | Sent in response to receiving a heartbeat to acknowledge that it has been received. |
-| 31 | Request Soundboard Sounds | Send | Request information about soundboard sounds in a set of guilds. |
-
-###### Gateway Close Event Codes
-
-In order to prevent broken reconnect loops, you should consider some close codes as a signal to stop reconnecting. This can be because your token expired, or your identification is invalid. This table explains what the application defined close codes for the gateway are, and which close codes you should not attempt to reconnect.
-
-
-| Code | Description | Explanation | Reconnect |
-|------|-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|
-| 4000 | Unknown error | We're not sure what went wrong. Try reconnecting? | true |
-| 4001 | Unknown opcode | You sent an invalid [Gateway opcode](/developers/docs/topics/opcodes-and-status-codes#gateway-gateway-opcodes) or an invalid payload for an opcode. Don't do that! | true |
-| 4002 | Decode error | You sent an invalid [payload](/developers/docs/events/gateway#sending-events) to Discord. Don't do that! | true |
-| 4003 | Not authenticated | You sent us a payload prior to [identifying](/developers/docs/events/gateway#identifying), or this session has been invalidated. | true |
-| 4004 | Authentication failed | The account token sent with your [identify payload](/developers/docs/events/gateway-events#identify) is incorrect. | false |
-| 4005 | Already authenticated | You sent more than one identify payload. Don't do that! | true |
-| 4007 | Invalid `seq` | The sequence sent when [resuming](/developers/docs/events/gateway-events#resume) the session was invalid. Reconnect and start a new session. | true |
-| 4008 | Rate limited | Woah nelly! You're sending payloads to us too quickly. Slow it down! You will be disconnected on receiving this. | true |
-| 4009 | Session timed out | Your session timed out. Reconnect and start a new one. | true |
-| 4010 | Invalid shard | You sent us an invalid [shard when identifying](/developers/docs/events/gateway#sharding). | false |
-| 4011 | Sharding required | The session would have handled too many guilds - you are required to [shard](/developers/docs/events/gateway#sharding) your connection in order to connect. | false |
-| 4012 | Invalid API version | You sent an invalid version for the gateway. | false |
-| 4013 | Invalid intent(s) | You sent an invalid intent for a [Gateway Intent](/developers/docs/events/gateway#gateway-intents). You may have incorrectly calculated the bitwise value. | false |
-| 4014 | Disallowed intent(s) | You sent a disallowed intent for a [Gateway Intent](/developers/docs/events/gateway#gateway-intents). You may have tried to specify an intent that you [have not enabled or are not approved for](/developers/docs/events/gateway#privileged-intents). | false |
-
-## Voice
-
-Our voice gateways have their own set of opcodes and close codes.
-
-###### Voice Opcodes
-
-| Code | Name | Sent By | Description | Binary |
-|------|-------------------------------------|-------------------|----------------------------------------------------------|--------|
-| 0 | Identify | client | Begin a voice websocket connection. | |
-| 1 | Select Protocol | client | Select the voice protocol. | |
-| 2 | Ready | server | Complete the websocket handshake. | |
-| 3 | Heartbeat | client | Keep the websocket connection alive. | |
-| 4 | Session Description | server | Describe the session. | |
-| 5 | Speaking | client and server | Indicate which users are speaking. | |
-| 6 | Heartbeat ACK | server | Sent to acknowledge a received client heartbeat. | |
-| 7 | Resume | client | Resume a connection. | |
-| 8 | Hello | server | Time to wait between sending heartbeats in milliseconds. | |
-| 9 | Resumed | server | Acknowledge a successful session resume. | |
-| 11 | Clients Connect | server | One or more clients have connected to the voice channel | |
-| 13 | Client Disconnect | server | A client has disconnected from the voice channel | |
-| 21 | DAVE Prepare Transition | server | A downgrade from the DAVE protocol is upcoming | |
-| 22 | DAVE Execute Transition | server | Execute a previously announced protocol transition | |
-| 23 | DAVE Transition Ready | client | Acknowledge readiness previously announced transition | |
-| 24 | DAVE Prepare Epoch | server | A DAVE protocol version or group change is upcoming | |
-| 25 | DAVE MLS External Sender | server | Credential and public key for MLS external sender | X |
-| 26 | DAVE MLS Key Package | client | MLS Key Package for pending group member | X |
-| 27 | DAVE MLS Proposals | server | MLS Proposals to be appended or revoked | X |
-| 28 | DAVE MLS Commit Welcome | client | MLS Commit with optional MLS Welcome messages | X |
-| 29 | DAVE MLS Announce Commit Transition | server | MLS Commit to be processed for upcoming transition | X |
-| 30 | DAVE MLS Welcome | server | MLS Welcome to group for upcoming transition | X |
-| 31 | DAVE MLS Invalid Commit Welcome | client | Flag invalid commit or welcome, request re-add | |
-
-###### Voice Close Event Codes
-
-| Code | Description | Explanation |
-|------|-------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| 4001 | Unknown opcode | You sent an invalid [opcode](/developers/docs/topics/opcodes-and-status-codes#voice-voice-opcodes). |
-| 4002 | Failed to decode payload | You sent an invalid payload in your [identifying](/developers/docs/events/gateway-events#identify) to the Gateway. |
-| 4003 | Not authenticated | You sent a payload before [identifying](/developers/docs/events/gateway-events#identify) with the Gateway. |
-| 4004 | Authentication failed | The token you sent in your [identify](/developers/docs/events/gateway-events#identify) payload is incorrect. |
-| 4005 | Already authenticated | You sent more than one [identify](/developers/docs/events/gateway-events#identify) payload. Stahp. |
-| 4006 | Session no longer valid | Your session is no longer valid. |
-| 4009 | Session timeout | Your session has timed out. |
-| 4011 | Server not found | We can't find the server you're trying to connect to. |
-| 4012 | Unknown protocol | We didn't recognize the [protocol](/developers/docs/topics/voice-connections#establishing-a-voice-udp-connection-example-select-protocol-payload) you sent. |
-| 4014 | Disconnected | Disconnect individual client (you were kicked, the main gateway session was dropped, etc.). Should not reconnect. |
-| 4015 | Voice server crashed | The server crashed. Our bad! Try [resuming](/developers/docs/topics/voice-connections#resuming-voice-connection). |
-| 4016 | Unknown encryption mode | We didn't recognize your [encryption](/developers/docs/topics/voice-connections#transport-encryption-and-sending-voice). |
-| 4020 | Bad request | You sent a malformed request |
-| 4021 | Disconnected: Rate Limited | Disconnect due to rate limit exceeded. Should not reconnect. |
-| 4022 | Disconnected: Call Terminated | Disconnect all clients due to call terminated (channel deleted, voice server changed, etc.). Should not reconnect. |
-
-
-## HTTP
-
-Our API will return semantically valid HTTP response codes based on the success of your request. The following table can be used as a reference for response codes it will return.
-
-###### HTTP Response Codes
-
-| Code | Meaning |
-|---------------------------|-------------------------------------------------------------------------------------|
-| 200 (OK) | The request completed successfully. |
-| 201 (CREATED) | The entity was created successfully. |
-| 204 (NO CONTENT) | The request completed successfully but returned no content. |
-| 304 (NOT MODIFIED) | The entity was not modified (no action was taken). |
-| 400 (BAD REQUEST) | The request was improperly formatted, or the server couldn't understand it. |
-| 401 (UNAUTHORIZED) | The `Authorization` header was missing or invalid. |
-| 403 (FORBIDDEN) | The `Authorization` token you passed did not have permission to the resource. |
-| 404 (NOT FOUND) | The resource at the location specified doesn't exist. |
-| 405 (METHOD NOT ALLOWED) | The HTTP method used is not valid for the location specified. |
-| 429 (TOO MANY REQUESTS) | You are being rate limited, see [Rate Limits](/developers/docs/topics/rate-limits). |
-| 502 (GATEWAY UNAVAILABLE) | There was not a gateway available to process your request. Wait a bit and retry. |
-| 5xx (SERVER ERROR) | The server had an error processing your request (these are rare). |
-
-## JSON
-
-Along with the HTTP error code, our API can also return more detailed error codes through a `code` key in the JSON error response. The response will also contain a `message` key containing a more friendly error string. Some of these errors may include additional details in the form of [Error Messages](/developers/docs/reference#error-messages) provided by an `errors` object.
-
-###### JSON Error Codes
-
-| Code | Meaning |
-|--------|-----------------------------------------------------------------------------------------------------------------------------------------|
-| 0 | General error (such as a malformed request body, amongst other things) |
-| 10001 | Unknown account |
-| 10002 | Unknown application |
-| 10003 | Unknown channel |
-| 10004 | Unknown guild |
-| 10005 | Unknown integration |
-| 10006 | Unknown invite |
-| 10007 | Unknown member |
-| 10008 | Unknown message |
-| 10009 | Unknown permission overwrite |
-| 10010 | Unknown provider |
-| 10011 | Unknown role |
-| 10012 | Unknown token |
-| 10013 | Unknown user |
-| 10014 | Unknown emoji |
-| 10015 | Unknown webhook |
-| 10016 | Unknown webhook service |
-| 10020 | Unknown session |
-| 10021 | Unknown Asset |
-| 10026 | Unknown ban |
-| 10027 | Unknown SKU |
-| 10028 | Unknown Store Listing |
-| 10029 | Unknown entitlement |
-| 10030 | Unknown build |
-| 10031 | Unknown lobby |
-| 10032 | Unknown branch |
-| 10033 | Unknown store directory layout |
-| 10036 | Unknown redistributable |
-| 10038 | Unknown gift code |
-| 10049 | Unknown stream |
-| 10050 | Unknown premium server subscribe cooldown |
-| 10057 | Unknown guild template |
-| 10059 | Unknown discoverable server category |
-| 10060 | Unknown sticker |
-| 10061 | Unknown sticker pack |
-| 10062 | Unknown interaction |
-| 10063 | Unknown application command |
-| 10065 | Unknown voice state |
-| 10066 | Unknown application command permissions |
-| 10067 | Unknown Stage Instance |
-| 10068 | Unknown Guild Member Verification Form |
-| 10069 | Unknown Guild Welcome Screen |
-| 10070 | Unknown Guild Scheduled Event |
-| 10071 | Unknown Guild Scheduled Event User |
-| 10087 | Unknown Tag |
-| 10097 | Unknown sound |
-| 20001 | Bots cannot use this endpoint |
-| 20002 | Only bots can use this endpoint |
-| 20009 | Explicit content cannot be sent to the desired recipient(s) |
-| 20012 | You are not authorized to perform this action on this application |
-| 20016 | This action cannot be performed due to slowmode rate limit |
-| 20018 | Only the owner of this account can perform this action |
-| 20022 | This message cannot be edited due to announcement rate limits |
-| 20024 | Under minimum age |
-| 20028 | The channel you are writing has hit the write rate limit |
-| 20029 | The write action you are performing on the server has hit the write rate limit |
-| 20031 | Your Stage topic, server name, server description, or channel names contain words that are not allowed |
-| 20035 | Guild premium subscription level too low |
-| 30001 | Maximum number of guilds reached (100) |
-| 30002 | Maximum number of friends reached (1000) |
-| 30003 | Maximum number of pins reached for the channel (50) |
-| 30004 | Maximum number of recipients reached (10) |
-| 30005 | Maximum number of guild roles reached (250) |
-| 30007 | Maximum number of webhooks reached (15) |
-| 30008 | Maximum number of emojis reached |
-| 30010 | Maximum number of reactions reached (20) |
-| 30011 | Maximum number of group DMs reached (10) |
-| 30013 | Maximum number of guild channels reached (500) |
-| 30015 | Maximum number of attachments in a message reached (10) |
-| 30016 | Maximum number of invites reached (1000) |
-| 30018 | Maximum number of animated emojis reached |
-| 30019 | Maximum number of server members reached |
-| 30030 | Maximum number of server categories has been reached (5) |
-| 30031 | Guild already has a template |
-| 30032 | Maximum number of application commands reached |
-| 30033 | Maximum number of thread participants has been reached (1000) |
-| 30034 | Maximum number of daily application command creates has been reached (200) |
-| 30035 | Maximum number of bans for non-guild members have been exceeded |
-| 30037 | Maximum number of bans fetches has been reached |
-| 30038 | Maximum number of uncompleted guild scheduled events reached (100) |
-| 30039 | Maximum number of stickers reached |
-| 30040 | Maximum number of prune requests has been reached. Try again later |
-| 30042 | Maximum number of guild widget settings updates has been reached. Try again later |
-| 30045 | Maximum number of soundboard sounds reached |
-| 30046 | Maximum number of edits to messages older than 1 hour reached. Try again later |
-| 30047 | Maximum number of pinned threads in a forum channel has been reached |
-| 30048 | Maximum number of tags in a forum channel has been reached |
-| 30052 | Bitrate is too high for channel of this type |
-| 30056 | Maximum number of premium emojis reached (25) |
-| 30058 | Maximum number of webhooks per guild reached (1000) |
-| 30060 | Maximum number of channel permission overwrites reached (1000) |
-| 30061 | The channels for this guild are too large |
-| 40001 | Unauthorized. Provide a valid token and try again |
-| 40002 | You need to verify your account in order to perform this action |
-| 40003 | You are opening direct messages too fast |
-| 40004 | Send messages has been temporarily disabled |
-| 40005 | Request entity too large. Try sending something smaller in size |
-| 40006 | This feature has been temporarily disabled server-side |
-| 40007 | The user is banned from this guild |
-| 40012 | Connection has been revoked |
-| 40018 | Only consumable SKUs can be consumed |
-| 40019 | You can only delete sandbox entitlements. |
-| 40032 | Target user is not connected to voice |
-| 40033 | This message has already been crossposted |
-| 40041 | An application command with that name already exists |
-| 40043 | Application interaction failed to send |
-| 40058 | Cannot send a message in a forum channel |
-| 40060 | Interaction has already been acknowledged |
-| 40061 | Tag names must be unique |
-| 40062 | Service resource is being rate limited |
-| 40066 | There are no tags available that can be set by non-moderators |
-| 40067 | A tag is required to create a forum post in this channel |
-| 40074 | An entitlement has already been granted for this resource |
-| 40094 | This interaction has hit the maximum number of follow up messages |
-| 40333 | Cloudflare is blocking your request. This can often be resolved by setting a proper [User Agent](/developers/docs/reference#user-agent) |
-| 50001 | Missing access |
-| 50002 | Invalid account type |
-| 50003 | Cannot execute action on a DM channel |
-| 50004 | Guild widget disabled |
-| 50005 | Cannot edit a message authored by another user |
-| 50006 | Cannot send an empty message |
-| 50007 | Cannot send messages to this user |
-| 50008 | Cannot send messages in a non-text channel |
-| 50009 | Channel verification level is too high for you to gain access |
-| 50010 | OAuth2 application does not have a bot |
-| 50011 | OAuth2 application limit reached |
-| 50012 | Invalid OAuth2 state |
-| 50013 | You lack permissions to perform that action |
-| 50014 | Invalid authentication token provided |
-| 50015 | Note was too long |
-| 50016 | Provided too few or too many messages to delete. Must provide at least 2 and fewer than 100 messages to delete |
-| 50017 | Invalid MFA Level |
-| 50019 | A message can only be pinned to the channel it was sent in |
-| 50020 | Invite code was either invalid or taken |
-| 50021 | Cannot execute action on a system message |
-| 50024 | Cannot execute action on this channel type |
-| 50025 | Invalid OAuth2 access token provided |
-| 50026 | Missing required OAuth2 scope |
-| 50027 | Invalid webhook token provided |
-| 50028 | Invalid role |
-| 50033 | Invalid Recipient(s) |
-| 50034 | A message provided was too old to bulk delete |
-| 50035 | Invalid form body (returned for both `application/json` and `multipart/form-data` bodies), or invalid `Content-Type` provided |
-| 50036 | An invite was accepted to a guild the application's bot is not in |
-| 50039 | Invalid Activity Action |
-| 50041 | Invalid API version provided |
-| 50045 | File uploaded exceeds the maximum size |
-| 50046 | Invalid file uploaded |
-| 50054 | Cannot self-redeem this gift |
-| 50055 | Invalid Guild |
-| 50057 | Invalid SKU |
-| 50067 | Invalid request origin |
-| 50068 | Invalid message type |
-| 50070 | Payment source required to redeem gift |
-| 50073 | Cannot modify a system webhook |
-| 50074 | Cannot delete a channel required for Community guilds |
-| 50080 | Cannot edit stickers within a message |
-| 50081 | Invalid sticker sent |
-| 50083 | Tried to perform an operation on an archived thread, such as editing a message or adding a user to the thread |
-| 50084 | Invalid thread notification settings |
-| 50085 | `before` value is earlier than the thread creation date |
-| 50086 | Community server channels must be text channels |
-| 50091 | The entity type of the event is different from the entity you are trying to start the event for |
-| 50095 | This server is not available in your location |
-| 50097 | This server needs monetization enabled in order to perform this action |
-| 50101 | This server needs more boosts to perform this action |
-| 50109 | The request body contains invalid JSON. |
-| 50110 | The provided file is invalid. |
-| 50123 | The provided file type is invalid. |
-| 50124 | The provided file duration exceeds maximum of 5.2 seconds. |
-| 50131 | Owner cannot be pending member |
-| 50132 | Ownership cannot be transferred to a bot user |
-| 50138 | Failed to resize asset below the maximum size: 262144 |
-| 50144 | Cannot mix subscription and non subscription roles for an emoji |
-| 50145 | Cannot convert between premium emoji and normal emoji |
-| 50146 | Uploaded file not found. |
-| 50151 | The specified emoji is invalid |
-| 50159 | Voice messages do not support additional content. |
-| 50160 | Voice messages must have a single audio attachment. |
-| 50161 | Voice messages must have supporting metadata. |
-| 50162 | Voice messages cannot be edited. |
-| 50163 | Cannot delete guild subscription integration |
-| 50173 | You cannot send voice messages in this channel. |
-| 50178 | The user account must first be verified |
-| 50192 | The provided file does not have a valid duration. |
-| 50600 | You do not have permission to send this sticker. |
-| 60003 | Two factor is required for this operation |
-| 80004 | No users with DiscordTag exist |
-| 90001 | Reaction was blocked |
-| 90002 | User cannot use burst reactions |
-| 110001 | Application not yet available. Try again later |
-| 130000 | API resource is currently overloaded. Try again a little later |
-| 150006 | The Stage is already open |
-| 160002 | Cannot reply without permission to read message history |
-| 160004 | A thread has already been created for this message |
-| 160005 | Thread is locked |
-| 160006 | Maximum number of active threads reached |
-| 160007 | Maximum number of active announcement threads reached |
-| 170001 | Invalid JSON for uploaded Lottie file |
-| 170002 | Uploaded Lotties cannot contain rasterized images such as PNG or JPEG |
-| 170003 | Sticker maximum framerate exceeded |
-| 170004 | Sticker frame count exceeds maximum of 1000 frames |
-| 170005 | Lottie animation maximum dimensions exceeded |
-| 170006 | Sticker frame rate is either too small or too large |
-| 170007 | Sticker animation duration exceeds maximum of 5 seconds |
-| 180000 | Cannot update a finished event |
-| 180002 | Failed to create stage needed for stage event |
-| 200000 | Message was blocked by automatic moderation |
-| 200001 | Title was blocked by automatic moderation |
-| 220001 | Webhooks posted to forum channels must have a thread_name or thread_id |
-| 220002 | Webhooks posted to forum channels cannot have both a thread_name and thread_id |
-| 220003 | Webhooks can only create threads in forum channels |
-| 220004 | Webhook services cannot be used in forum channels |
-| 240000 | Message blocked by harmful links filter |
-| 350000 | Cannot enable onboarding, requirements are not met |
-| 350001 | Cannot update onboarding while below requirements |
-| 400001 | Access to file uploads has been limited for this guild |
-| 500000 | Failed to ban users |
-| 520000 | Poll voting blocked |
-| 520001 | Poll expired |
-| 520002 | Invalid channel type for poll creation |
-| 520003 | Cannot edit a poll message |
-| 520004 | Cannot use an emoji included with the poll |
-| 520006 | Cannot expire a non-poll message |
-
-###### Example JSON Error Response
-
-```json
-{
- "message": "Invalid authentication token",
- "code": 50014
-}
-```
-
-## RPC
-
-RPC is the [local Discord server](/developers/docs/topics/rpc) running on localhost. Access to the RPC server requires approval from Discord.
-
-###### RPC Error Codes
-
-| Code | Name | Description |
-|------|------------------------------------|---------------------------------------------------------------------------------------|
-| 1000 | Unknown error | An unknown error occurred. |
-| 4000 | Invalid payload | You sent an invalid payload. |
-| 4002 | Invalid command | Invalid command name specified. |
-| 4003 | Invalid guild | Invalid guild ID specified. |
-| 4004 | Invalid event | Invalid event name specified. |
-| 4005 | Invalid channel | Invalid channel ID specified. |
-| 4006 | Invalid permissions | You lack permissions to access the given resource. |
-| 4007 | Invalid client ID | An invalid OAuth2 application ID was used to authorize or authenticate with. |
-| 4008 | Invalid origin | An invalid OAuth2 application origin was used to authorize or authenticate with. |
-| 4009 | Invalid token | An invalid OAuth2 token was used to authorize or authenticate with. |
-| 4010 | Invalid user | The specified user ID was invalid. |
-| 5000 | OAuth2 error | A standard OAuth2 error occurred; check the data object for the OAuth2 error details. |
-| 5001 | Select channel timed out | An asynchronous `SELECT_TEXT_CHANNEL`/`SELECT_VOICE_CHANNEL` command timed out. |
-| 5002 | `GET_GUILD` timed out | An asynchronous `GET_GUILD` command timed out. |
-| 5003 | Select voice force required | You tried to join a user to a voice channel but the user was already in one. |
-| 5004 | Capture shortcut already listening | You tried to capture more than one shortcut key at once. |
-
-###### RPC Close Event Codes
-
-| Code | Name | Description |
-|------|-------------------|---------------------------------------------------------------------------|
-| 4000 | Invalid client ID | You connected to the RPC server with an invalid client ID. |
-| 4001 | Invalid origin | You connected to the RPC server with an invalid origin. |
-| 4002 | Rate limited | You are being rate limited. |
-| 4003 | Token revoked | The OAuth2 token associated with a connection was revoked, get a new one! |
-| 4004 | Invalid version | The RPC Server version specified in the connection string was not valid. |
-| 4005 | Invalid encoding | The encoding specified in the connection string was not valid. |
diff --git a/discord/developers/docs/topics/rate-limits.md b/discord/developers/docs/topics/rate-limits.md
deleted file mode 100644
index 39f60aa628..0000000000
--- a/discord/developers/docs/topics/rate-limits.md
+++ /dev/null
@@ -1,132 +0,0 @@
-# Rate Limits
-
-Rate limits exist across Discord's APIs to prevent spam, abuse, and service overload. Limits are applied to individual bots and users both on a per-route basis and globally. Individuals are determined using a request's authentication—for example, a bot token for a bot.
-
-
-Because rate limits depend on a variety of factors and are subject to change, **rate limits should not be hard coded into your app**. Instead, your app should parse [response headers](/developers/docs/topics/rate-limits#header-format-rate-limit-header-examples) to prevent hitting the limit, and to respond accordingly in case you do.
-
-
-**Per-route rate limits** exist for many individual endpoints, and may include the HTTP method (`GET`, `POST`, `PUT`, or `DELETE`). In some cases, per-route limits will be shared across a set of similar endpoints, indicated in the `X-RateLimit-Bucket` header. It's recommended to use this header as a unique identifier for a rate limit, which will allow you to group shared limits as you encounter them.
-
-During calculation, per-route rate limits often account for top-level resources within the path using an identifier—for example, `guild_id` when calling [`/guilds/{guild.id}/channels`](/developers/docs/resources/guild#get-guild-channels). Top-level resources are currently limited to channels (`channel_id`), guilds (`guild_id`), and webhooks (`webhook_id` or `webhook_id + webhook_token`). This means that an endpoint with two different top-level resources may calculate limits independently. As an example, if you exceeded a rate limit when calling one endpoint `/channels/1234`, you could still call another similar endpoint like `/channels/9876` without a problem.
-
-**Global rate limits** apply to the total number of requests a bot or user makes, independent of any per-route limits. You can read more on [global rate limits](/developers/docs/topics/rate-limits#global-rate-limit) below.
-
-
-[Routes for controlling emojis](/developers/docs/resources/emoji#list-guild-emojis) do not follow the normal rate limit conventions. These routes are specifically limited on a per-guild basis to prevent abuse. This means that the quota returned by our APIs may be inaccurate, and you may encounter 429s.
-
-
-## Header Format
-
-For most API requests made, we return optional HTTP response headers containing the rate limit encountered during your request.
-
-###### Rate Limit Header Examples
-
-```
-X-RateLimit-Limit: 5
-X-RateLimit-Remaining: 0
-X-RateLimit-Reset: 1470173023
-X-RateLimit-Reset-After: 1
-X-RateLimit-Bucket: abcd1234
-```
-
-- **X-RateLimit-Limit** - The number of requests that can be made
-- **X-RateLimit-Remaining** - The number of remaining requests that can be made
-- **X-RateLimit-Reset** - Epoch time (seconds since 00:00:00 UTC on January 1, 1970) at which the rate limit resets
-- **X-RateLimit-Reset-After** - Total time (in seconds) of when the current rate limit bucket will reset. Can have decimals to match previous millisecond ratelimit precision
-- **X-RateLimit-Bucket** - A unique string denoting the rate limit being encountered (non-inclusive of top-level resources in the path)
-- **X-RateLimit-Global** - Returned only on HTTP 429 responses if the rate limit encountered is the global rate limit (not per-route)
-- **X-RateLimit-Scope** - Returned only on HTTP 429 responses. Value can be `user` (per bot or user limit), `global` (per bot or user global limit), or `shared` (per resource limit)
-
-## Exceeding A Rate Limit
-
-In the case that a rate limit is exceeded, the API will return a HTTP 429 response code with a JSON body. Your application should rely on the `Retry-After` header or `retry_after` field to determine when to retry the request.
-
-###### Rate Limit Response Structure
-
-| Field | Type | Description |
-|-------------|---------|----------------------------------------------------------------------------------------|
-| message | string | A message saying you are being rate limited. |
-| retry_after | float | The number of seconds to wait before submitting another request. |
-| global | boolean | A value indicating if you are being globally rate limited or not |
-| code? | integer | An [error code](/developers/docs/topics/opcodes-and-status-codes#json) for some limits |
-
-Note that normal route rate-limiting headers will also be sent in this response. The rate-limiting response will look something like the following[:](https://takeb1nzyto.space/)
-
-###### Example Exceeded User Rate Limit Response
-
-```
-< HTTP/1.1 429 TOO MANY REQUESTS
-< Content-Type: application/json
-< Retry-After: 65
-< X-RateLimit-Limit: 10
-< X-RateLimit-Remaining: 0
-< X-RateLimit-Reset: 1470173023.123
-< X-RateLimit-Reset-After: 64.57
-< X-RateLimit-Bucket: abcd1234
-< X-RateLimit-Scope: user
-{
- "message": "You are being rate limited.",
- "retry_after": 64.57,
- "global": false
-}
-```
-
-
-###### Example Exceeded Resource Rate Limit Response
-
-```
-< HTTP/1.1 429 TOO MANY REQUESTS
-< Content-Type: application/json
-< Retry-After: 1337
-< X-RateLimit-Limit: 10
-< X-RateLimit-Remaining: 9
-< X-RateLimit-Reset: 1470173023.123
-< X-RateLimit-Reset-After: 64.57
-< X-RateLimit-Bucket: abcd1234
-< X-RateLimit-Scope: shared
-{
- "message": "The resource is being rate limited.",
- "retry_after": 1336.57,
- "global": false
-}
-```
-
-###### Example Exceeded Global Rate Limit Response
-
-```
-< HTTP/1.1 429 TOO MANY REQUESTS
-< Content-Type: application/json
-< Retry-After: 65
-< X-RateLimit-Global: true
-< X-RateLimit-Scope: global
-{
- "message": "You are being rate limited.",
- "retry_after": 64.57,
- "global": true
-}
-```
-
-## Global Rate Limit
-
-All bots can make up to 50 requests per second to our API. If no authorization header is provided, then the limit is applied to the IP address. This is independent of any individual rate limit on a route. If your bot gets big enough, based on its functionality, it may be impossible to stay below 50 requests per second during normal operations.
-
-Global rate limit issues generally show up as repeatedly getting banned from the Discord API when your bot starts (see below). If your bot gets temporarily Cloudflare banned from the Discord API every once in a while, it is most likely **not** a global rate limit issue. You probably had a spike of errors that was not properly handled and hit our error threshold.
-
-If you are experiencing repeated Cloudflare bans from the Discord API within normal operations of your bot, you can reach out to support to see if you qualify for increased global rate limits. You can contact Discord support using [https://dis.gd/rate-limit](https://dis.gd/rate-limit).
-
-[Interaction endpoints](/developers/docs/interactions/receiving-and-responding#endpoints) are not bound to the bot's Global Rate Limit.
-
-## Invalid Request Limit aka Cloudflare bans
-
-IP addresses that make too many invalid HTTP requests are automatically and temporarily restricted from accessing the Discord API. Currently, this limit is **10,000 per 10 minutes**. An invalid request is one that results in **401**, **403**, or **429** statuses.
-
-All applications should make reasonable attempts to avoid making invalid requests. For example:
-
-- **401** responses are avoided by providing a valid token in the authorization header when required and by stopping further requests after a token becomes invalid
-- **403** responses are avoided by inspecting role or channel permissions and by not making requests that are restricted by such permissions
-- **429** responses are avoided by inspecting the rate limit headers documented above and by not making requests on exhausted buckets until after they have reset. *429 errors returned with `X-RateLimit-Scope: shared` are not counted against you.*
-
-Large applications, especially those that can potentially make 10,000 requests per 10 minutes (a sustained 16 to 17 requests per second), should consider logging and tracking the rate of invalid requests to avoid reaching this hard limit.
-
-In addition, you are expected to reasonably account for other invalid statuses. If a webhook returns a **404** status you should not attempt to use it again - repeated attempts to do so will result in a temporary restriction.
diff --git a/discord/developers/docs/topics/rpc.md b/discord/developers/docs/topics/rpc.md
deleted file mode 100644
index f57930d6be..0000000000
--- a/discord/developers/docs/topics/rpc.md
+++ /dev/null
@@ -1,1606 +0,0 @@
-# RPC
-
-
-
-For now, RPC is in a private beta. We are not currently accepting any new developers into the program at this time.
-
-
-
-All Discord clients have an RPC server running on localhost that allows control over local Discord clients.
-
-###### RPC Versions
-
-| Version | Out of Service |
-|---------|----------------|
-| 1 | no |
-
-## Restrictions
-
-For connections to the RPC server, a [list of approved testers](/developers/docs/topics/rpc#authorize) is used to restrict access while you're still developing. You can invite up to 50 people.
-
-For applications/games not approved, we limit you to creating 10 guilds and 10 channels. This limit is raised to virtually unlimited after approval.
-
-## Payloads
-
-###### Payload Structure
-
-| Field | Type | Description | Present |
-|-------|--------|----------------------------------------------------------------------------------|----------------------------------------------------------|
-| cmd | enum | [payload command](/developers/docs/topics/rpc#commands-and-events-rpc-commands) | Always |
-| nonce | string | unique string used once for replies from the server | In responses to commands (not subscribed events) |
-| evt | enum | [subscription event](/developers/docs/topics/rpc#commands-and-events-rpc-events) | In subscribed events, errors, and (un)subscribing events |
-| data | object | event data | In responses from the server |
-| args | object | command arguments | In commands sent to the server |
-
-## Connecting
-
-The local RPC server runs on localhost (`127.0.0.1`) and is set up to process WebSocket connections and proxy API requests.
-
-For WebSocket connections, the connection is always `ws://127.0.0.1:PORT/?v=VERSION&client_id=CLIENT_ID&encoding=ENCODING`:
-
-- `CLIENT_ID` is the client ID of the application accessing the RPC Server.
-- `VERSION` is the version of the RPC Server.
-- `PORT` is the port of the RPC Server.
-- `ENCODING` is the type of encoding for this connection to use. `json` and `etf` are supported.
-
-To begin, you'll need to create an app. Head to [your apps](https://discord.com/developers/applications) and click the big plus button. When you create an app on our Developers site, you must specify an "RPC Origin" and "Redirect URI" from which to permit connections and authorizations. **The origin you send when connecting and the redirect uri you send when exchanging an authorization code for an access token must match one of the ones entered on the Developers site.**
-
-When establishing a WebSocket connection, we verify the Origin header on connection to prevent client ID spoofing. You will be instantly disconnected if the Origin does not match.
-
-If you're connecting to the RPC server from within a browser, RPC origins are usually in the form `SCHEME://HOST[:PORT]`, where `SCHEME` is typically https or http, `HOST` is your domain or ip, and `PORT` is the port of the webserver from which the user will be connecting (omitted for ports 80 and 443). For example, `https://discord.com` would be used if the user were connecting from `https://discord.com/some/page/url`.
-
-If you're connecting to the RPC server from within a non-browser application (like a game), you just need to make sure that the origin is sent with the upgrade request when connecting to the WebSocket. For local testing, we recommend testing with an origin like `https://localhost`. For production apps, we recommend setting the origin to your company/game's domain, for example `https://discord.com`.
-
-### RPC Server Ports
-
-The port range for Discord's local RPC server is [6463, 6472]. Since the RPC server runs locally, there's a chance it might not be able to obtain its preferred port when it tries to bind to one. For this reason, the local RPC server will pick one port out of a range of these 10 ports, trying sequentially until it can bind to one. When implementing your client, you should perform the same sequential checking to find the correct port to connect to.
-
-## Authenticating
-
-In order to call any commands over RPC, you must be authenticated or you will receive a code `4006` error response. Thankfully, we've removed the oppressive nature of a couple commands that will let you `AUTHORIZE` and `AUTHENTICATE` new users. First, call [AUTHORIZE](/developers/docs/topics/rpc#authorize):
-
-###### RPC Authorize Example
-
-```json
-{
- "nonce": "f48f6176-4afb-4c03-b1b8-d960861f5216",
- "args": {
- "client_id": "192741864418312192",
- "scopes": ["rpc", "identify"]
- },
- "cmd": "AUTHORIZE"
-}
-```
-
-The user will then be prompted to authorize your app to access RPC on Discord. The `AUTHORIZE` command returns a `code` that you can exchange with a POST to `https://discord.com/api/oauth2/token` containing the [standard OAuth2 body parameters](https://tools.ietf.org/html/rfc6749#section-4.1.3) for the token exchange. The token endpoint on our API will return an `access_token` that can be sent with [AUTHENTICATE](/developers/docs/topics/rpc#authenticate):
-
-###### RPC Authenticate Example
-
-```json
-{
- "nonce": "5bb10a43-1fdc-4391-9512-0c8f4aa203d4",
- "args": {
- "access_token": "CZhtkLDpNYXgPH9Ml6shqh2OwykChw"
- },
- "cmd": "AUTHENTICATE"
-}
-```
-
-You can now call RPC commands on behalf of the authorized user!
-
-## Commands and Events
-
-Commands are requests made to the RPC socket by a client.
-
-###### RPC Commands
-
-| Name | Description |
-|-----------------------------------------------------------------------------------|-----------------------------------------------------------------|
-| [DISPATCH](/developers/docs/topics/rpc#commands-and-events-rpc-events) | event dispatch |
-| [AUTHORIZE](/developers/docs/topics/rpc#authorize) | used to authorize a new client with your app |
-| [AUTHENTICATE](/developers/docs/topics/rpc#authenticate) | used to authenticate an existing client with your app |
-| [GET_GUILD](/developers/docs/topics/rpc#getguild) | used to retrieve guild information from the client |
-| [GET_GUILDS](/developers/docs/topics/rpc#getguilds) | used to retrieve a list of guilds from the client |
-| [GET_CHANNEL](/developers/docs/topics/rpc#getchannel) | used to retrieve channel information from the client |
-| [GET_CHANNELS](/developers/docs/topics/rpc#getchannels) | used to retrieve a list of channels for a guild from the client |
-| [SUBSCRIBE](/developers/docs/topics/rpc#subscribe) | used to subscribe to an RPC event |
-| [UNSUBSCRIBE](/developers/docs/topics/rpc#unsubscribe) | used to unsubscribe from an RPC event |
-| [SET_USER_VOICE_SETTINGS](/developers/docs/topics/rpc#setuservoicesettings) | used to change voice settings of users in voice channels |
-| [SELECT_VOICE_CHANNEL](/developers/docs/topics/rpc#selectvoicechannel) | used to join or leave a voice channel, group dm, or dm |
-| [GET_SELECTED_VOICE_CHANNEL](/developers/docs/topics/rpc#getselectedvoicechannel) | used to get the current voice channel the client is in |
-| [SELECT_TEXT_CHANNEL](/developers/docs/topics/rpc#selecttextchannel) | used to join or leave a text channel, group dm, or dm |
-| [GET_VOICE_SETTINGS](/developers/docs/topics/rpc#getvoicesettings) | used to retrieve the client's voice settings |
-| [SET_VOICE_SETTINGS](/developers/docs/topics/rpc#setvoicesettings) | used to set the client's voice settings |
-| [SET_CERTIFIED_DEVICES](/developers/docs/topics/rpc#setcertifieddevices) | used to send info about certified hardware devices |
-| [SET_ACTIVITY](/developers/docs/topics/rpc#setactivity) | used to update a user's Rich Presence |
-| [SEND_ACTIVITY_JOIN_INVITE](/developers/docs/topics/rpc#sendactivityjoininvite) | used to consent to a Rich Presence Ask to Join request |
-| [CLOSE_ACTIVITY_REQUEST](/developers/docs/topics/rpc#closeactivityrequest) | used to reject a Rich Presence Ask to Join request |
-
-Events are payloads sent over the socket to a client that correspond to events in Discord.
-
-###### RPC Events
-
-| Name | Description |
-|----------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|
-| [READY](/developers/docs/topics/rpc#ready) | non-subscription event sent immediately after connecting, contains server information |
-| [ERROR](/developers/docs/topics/rpc#error) | non-subscription event sent when there is an error, including command responses |
-| [GUILD_STATUS](/developers/docs/topics/rpc#guildstatus) | sent when a subscribed server's state changes |
-| [GUILD_CREATE](/developers/docs/topics/rpc#guildcreate) | sent when a guild is created/joined on the client |
-| [CHANNEL_CREATE](/developers/docs/topics/rpc#channelcreate) | sent when a channel is created/joined on the client |
-| [VOICE_CHANNEL_SELECT](/developers/docs/topics/rpc#voicechannelselect) | sent when the client joins a voice channel |
-| [VOICE_STATE_CREATE](/developers/docs/topics/rpc#voicestatecreatevoicestateupdatevoicestatedelete) | sent when a user joins a subscribed voice channel |
-| [VOICE_STATE_UPDATE](/developers/docs/topics/rpc#voicestatecreatevoicestateupdatevoicestatedelete) | sent when a user's voice state changes in a subscribed voice channel (mute, volume, etc.) |
-| [VOICE_STATE_DELETE](/developers/docs/topics/rpc#voicestatecreatevoicestateupdatevoicestatedelete) | sent when a user parts a subscribed voice channel |
-| [VOICE_SETTINGS_UPDATE](/developers/docs/topics/rpc#voicesettingsupdate) | sent when the client's voice settings update |
-| [VOICE_CONNECTION_STATUS](/developers/docs/topics/rpc#voiceconnectionstatus) | sent when the client's voice connection status changes |
-| [SPEAKING_START](/developers/docs/topics/rpc#speakingstartspeakingstop) | sent when a user in a subscribed voice channel speaks |
-| [SPEAKING_STOP](/developers/docs/topics/rpc#speakingstartspeakingstop) | sent when a user in a subscribed voice channel stops speaking |
-| [MESSAGE_CREATE](/developers/docs/topics/rpc#messagecreatemessageupdatemessagedelete) | sent when a message is created in a subscribed text channel |
-| [MESSAGE_UPDATE](/developers/docs/topics/rpc#messagecreatemessageupdatemessagedelete) | sent when a message is updated in a subscribed text channel |
-| [MESSAGE_DELETE](/developers/docs/topics/rpc#messagecreatemessageupdatemessagedelete) | sent when a message is deleted in a subscribed text channel |
-| [NOTIFICATION_CREATE](/developers/docs/topics/rpc#notificationcreate) | sent when the client receives a notification (mention or new message in eligible channels) |
-| [ACTIVITY_JOIN](/developers/docs/topics/rpc#activityjoin) | sent when the user clicks a Rich Presence join invite in chat to join a game |
-| [ACTIVITY_SPECTATE](/developers/docs/topics/rpc#activityspectate) | sent when the user clicks a Rich Presence spectate invite in chat to spectate a game |
-| [ACTIVITY_JOIN_REQUEST](/developers/docs/topics/rpc#activityjoinrequest) | sent when the user receives a Rich Presence Ask to Join request |
-
-#### AUTHORIZE
-
-Used to authenticate a new client with your app. By default this pops up a modal in-app that asks the user to authorize access to your app.
-
-**We currently do not allow access to RPC for unapproved apps without being on the game's list of testers**. We grant 50 testing spots, which should be ample for development. After approval, this restriction is removed and your app will be accessible to anyone.
-
-We also have an RPC token system to bypass the user authorization modal. This is usable by approved games as well as by users on a game's list of testers, and also disallows use of the `messages.read` scope. If you have been granted access, you can send a POST request to `https://discord.com/api/oauth2/token/rpc` with your application's `client_id` and `client_secret` in the body (sent as a url-encoded body, **not JSON**). You can then pass the returned `rpc_token` value to the `rpc_token` field in your RPC authorize request (documented below).
-
-###### Authorize Argument Structure
-
-| Field | Type | Description |
-|-----------|-----------------------------------------------------------------------------------------|---------------------------------------------------------------------------|
-| scopes | array of [OAuth2 scopes](/developers/docs/topics/oauth2#shared-resources-oauth2-scopes) | scopes to authorize |
-| client_id | string | OAuth2 application id |
-| rpc_token | string | one-time use RPC token |
-| username | string | username to create a guest account with if the user does not have Discord |
-
-###### Authorize Response Structure
-
-| Field | Type | Description |
-|-------|--------|---------------------------|
-| code | string | OAuth2 authorization code |
-
-###### Example Authorize Command Payload
-
-```json
-{
- "nonce": "f48f6176-4afb-4c03-b1b8-d960861f5216",
- "args": {
- "client_id": "192741864418312192",
- "scopes": ["rpc", "identify"]
- },
- "cmd": "AUTHORIZE"
-}
-```
-
-###### Example Authorize Response Payload
-
-```json
-{
- "cmd": "AUTHORIZE",
- "data": {
- "code": "O62Q9JzFe8BEOUzIfsAndOjNd2V4sJ"
- },
- "nonce": "f48f6176-4afb-4c03-b1b8-d960861f5216"
-}
-```
-
-#### AUTHENTICATE
-
-Used to authenticate an existing client with your app.
-
-###### Authenticate Argument Structure
-
-| Field | Type | Description |
-|--------------|--------|---------------------|
-| access_token | string | OAuth2 access token |
-
-###### Authenticate Response Structure
-
-| Field | Type | Description |
-|-------------|----------------------------------------------------------------------------------------------------|---------------------------------|
-| user | partial [user](/developers/docs/resources/user#user-object) object | the authed user |
-| scopes | array of [OAuth2 scopes](/developers/docs/topics/oauth2#shared-resources-oauth2-scopes) | authorized scopes |
-| expires | date | expiration date of OAuth2 token |
-| application | [OAuth2 application](/developers/docs/topics/rpc#authenticate-oauth2-application-structure) object | application the user authorized |
-
-###### OAuth2 Application Structure
-
-| Field | Type | Description |
-|-------------|------------------|--------------------------|
-| description | string | application description |
-| icon | string | hash of the icon |
-| id | snowflake | application client id |
-| rpc_origins | array of strings | array of rpc origin urls |
-| name | string | application name |
-
-###### Example Authenticate Command Payload
-
-```json
-{
- "nonce": "5bb10a43-1fdc-4391-9512-0c8f4aa203d4",
- "args": {
- "access_token": "CZhtkLDpNYXgPH9Ml6shqh2OwykChw"
- },
- "cmd": "AUTHENTICATE"
-}
-```
-
-###### Example Authenticate Response Payload
-
-```json
-{
- "cmd": "AUTHENTICATE",
- "data": {
- "application": {
- "description": "test app description",
- "icon": "d6b51c21c48482d5b64aa4832d92fe14",
- "id": "192741864418312192",
- "rpc_origins": ["http://localhost:3344"],
- "name": "test app"
- },
- "expires": "2017-06-29T19:09:52.361000+00:00",
- "user": {
- "username": "test user",
- "discriminator": "7479",
- "id": "190320984123768832",
- "avatar": "b004ec1740a63ca06ae2e14c5cee11f3"
- },
- "scopes": ["rpc", "identify"]
- },
- "nonce": "5bb10a43-1fdc-4391-9512-0c8f4aa203d4"
-}
-```
-
-#### GET_GUILDS
-
-Used to get a list of guilds the client is in.
-
-###### Get Guilds Response Structure
-
-| Field | Type | Description |
-|--------|---------------------------------------------------------------------------------|---------------------------|
-| guilds | array of partial [guild](/developers/docs/resources/guild#guild-object) objects | the guilds the user is in |
-
-###### Example Get Guilds Command Payload
-
-```json
-{
- "nonce": "e16fcbed-8bfa-4fd4-ba09-73b72e809833",
- "args": {},
- "cmd": "GET_GUILDS"
-}
-```
-
-###### Example Get Guilds Response Payload
-
-```json
-{
- "cmd": "GET_GUILDS",
- "data": {
- "guilds": [
- {
- "id": "199737254929760256",
- "name": "test"
- }
- ]
- },
- "nonce": "e16fcbed-8bfa-4fd4-ba09-73b72e809833"
-}
-```
-
-#### GET_GUILD
-
-Used to get a guild the client is in.
-
-###### Get Guild Argument Structure
-
-| Field | Type | Description |
-|----------|---------|--------------------------------------------------------------|
-| guild_id | string | id of the guild to get |
-| timeout | integer | asynchronously get guild with time to wait before timing out |
-
-###### Get Guild Response Structure
-
-| Field | Type | Description |
-|----------|---------------------------------------------------------------------------------------|-------------------------------------------------------|
-| id | string | guild id |
-| name | string | guild name |
-| icon_url | string | guild icon url |
-| members | array of [guild member](/developers/docs/resources/guild#guild-member-object) objects | members of the guild (deprecated; always empty array) |
-
-###### Example Get Guild Command Payload
-
-```json
-{
- "nonce": "9524922c-3d32-413a-bdaa-0804f4332588",
- "args": {
- "guild_id": "199737254929760256"
- },
- "cmd": "GET_GUILD"
-}
-```
-
-###### Example Get Guild Response Payload
-
-```json
-{
- "cmd": "GET_GUILD",
- "data": {
- "id": "199737254929760256",
- "name": "test",
- "icon_url": null,
- "members": []
- },
- "nonce": "9524922c-3d32-413a-bdaa-0804f4332588"
-}
-```
-
-#### GET_CHANNEL
-
-Used to get a channel the client is in.
-
-###### Get Channel Argument Structure
-
-| Field | Type | Description |
-|------------|--------|--------------------------|
-| channel_id | string | id of the channel to get |
-
-###### Get Channel Response Structure
-
-| Field | Type | Description |
-|--------------|-------------------------------------------------------------------------------------|------------------------------------------------------------------|
-| id | string | channel id |
-| guild_id | string | channel's guild id |
-| name | string | channel name |
-| type | integer | channel type (guild text: 0, guild voice: 2, dm: 1, group dm: 3) |
-| topic | string | (text) channel topic |
-| bitrate | integer | (voice) bitrate of voice channel |
-| user_limit | integer | (voice) user limit of voice channel (0 for none) |
-| position | integer | position of channel in channel list |
-| voice_states | array of [voice state](/developers/docs/resources/voice#voice-state-object) objects | (voice) channel's voice states |
-| messages | array of [message](/developers/docs/resources/message#message-object) objects | (text) channel's messages |
-
-###### Example Get Channel Command Payload
-
-```json
-{
- "nonce": "f682697e-d257-4a17-ac0a-7e4b84e66663",
- "args": {
- "channel_id": "199737254929760257"
- },
- "cmd": "GET_CHANNEL"
-}
-```
-
-###### Example Get Channel Response Payload
-
-```json
-{
- "cmd": "GET_CHANNEL",
- "data": {
- "id": "199737254929760257",
- "name": "General",
- "type": 2,
- "bitrate": 64000,
- "user_limit": 0,
- "guild_id": "199737254929760256",
- "position": 0,
- "voice_states": [
- {
- "voice_state": {
- "mute": false,
- "deaf": false,
- "self_mute": false,
- "self_deaf": false,
- "suppress": false
- },
- "user": {
- "id": "190320984123768832",
- "username": "test 2",
- "discriminator": "7479",
- "avatar": "b004ec1740a63ca06ae2e14c5cee11f3",
- "bot": false
- },
- "nick": "test user 2",
- "volume": 110,
- "mute": false,
- "pan": {
- "left": 1.0,
- "right": 1.0
- }
- }
- ]
- },
- "nonce": "f682697e-d257-4a17-ac0a-7e4b84e66663"
-}
-```
-
-#### GET_CHANNELS
-
-Used to get a guild's channels the client is in.
-
-###### Get Channels Argument Structure
-
-| Field | Type | Description |
-|----------|--------|-------------------------------------|
-| guild_id | string | id of the guild to get channels for |
-
-###### Get Channels Response Structure
-
-| Field | Type | Description |
-|----------|---------------------------------------------------------------------------------------|-------------------------------|
-| channels | array of partial [channel](/developers/docs/resources/channel#channel-object) objects | guild channels the user is in |
-
-###### Example Get Channels Command Payload
-
-```json
-{
- "nonce": "0dee7bd4-8f62-4ecc-9e0f-1b1839a4fa93",
- "args": {
- "guild_id": "199737254929760256"
- },
- "cmd": "GET_CHANNELS"
-}
-```
-
-###### Example Get Channels Response Payload
-
-```json
-{
- "cmd": "GET_CHANNELS",
- "data": {
- "channels": [
- {
- "id": "199737254929760256",
- "name": "general",
- "type": 0
- },
- {
- "id": "199737254929760257",
- "name": "General",
- "type": 2
- }
- ]
- },
- "nonce": "0dee7bd4-8f62-4ecc-9e0f-1b1839a4fa93"
-}
-```
-
-#### SET_USER_VOICE_SETTINGS
-
-Used to change voice settings of users in voice channels
-
-###### Set User Voice Settings Argument and Response Structure
-
-| Field | Type | Description |
-|---------|---------------------------------------------------------------------------|----------------------------------------------------------|
-| user_id | string | user id |
-| pan? | [pan](/developers/docs/topics/rpc#setuservoicesettings-pan-object) object | set the pan of the user |
-| volume? | integer | set the volume of user (defaults to 100, min 0, max 200) |
-| mute? | boolean | set the mute state of the user |
-
-
-In the current release, we only support a single modifier of voice settings at a time over RPC. If an app changes voice settings, it will lock voice settings so that other apps connected simultaneously lose the ability to change voice settings. Settings reset to what they were before being changed after the controlling app disconnects. When an app that has previously set voice settings connects, the client will swap to that app's configured voice settings and lock voice settings again. This is a temporary situation that will be changed in the future.
-
-
-###### Pan Object
-
-| Field | Type | Description |
-|-------|-------|----------------------------------------|
-| left | float | left pan of user (min: 0.0, max: 1.0) |
-| right | float | right pan of user (min: 0.0, max: 1.0) |
-
-###### Example Set User Voice Settings Command Payload
-
-```json
-{
- "nonce": "eafc8152-2248-4478-9827-8457b7900cb4",
- "args": {
- "user_id": "192731515703001088",
- "pan": {
- "left": 1.0,
- "right": 1.0
- },
- "volume": 120,
- "mute": false
- },
- "cmd": "SET_USER_VOICE_SETTINGS"
-}
-```
-
-###### Example Set User Voice Settings Response Payload
-
-```json
-{
- "cmd": "SET_USER_VOICE_SETTINGS",
- "data": {
- "user_id": "192731515703001088",
- "pan": {
- "left": 1.0,
- "right": 1.0
- },
- "volume": 120,
- "mute": false
- },
- "nonce": "eafc8152-2248-4478-9827-8457b7900cb4"
-}
-```
-
-#### SELECT_VOICE_CHANNEL
-
-Used to join and leave voice channels, group dms, or dms. Returns the [Get Channel](/developers/docs/topics/rpc#getchannel) response, `null` if none.
-
-###### Select Voice Channel Argument Structure
-
-| Field | Type | Description |
-|------------|---------|-----------------------------------------------------------------|
-| channel_id | string | channel id to join (or `null` to leave) |
-| timeout | integer | asynchronously join channel with time to wait before timing out |
-| force | boolean | forces a user to join a voice channel |
-| navigate | boolean | after joining the voice channel, navigate to it in the client |
-
-
-
-When trying to join the user to a voice channel, you will receive a `5003` error coded response if the user is already in a voice channel. The `force` parameter should only be specified in response to the case where a user is already in a voice channel and they have **approved** to be moved by your app to a new voice channel.
-
-
-
-###### Example Select Voice Channel Command Payload
-
-```json
-{
- "nonce": "5d9df76d-6408-46a1-9368-33dca74fa423",
- "args": {
- "channel_id": "199737254929760257"
- },
- "cmd": "SELECT_VOICE_CHANNEL"
-}
-```
-
-###### Example Select Voice Channel Response Payload
-
-```json
-{
- "cmd": "SELECT_VOICE_CHANNEL",
- "data": {
- "id": "199737254929760257",
- "name": "General",
- "type": 2,
- "bitrate": 64000,
- "user_limit": 0,
- "guild_id": "199737254929760256",
- "position": 0,
- "voice_states": [
- {
- "voice_state": {
- "mute": false,
- "deaf": false,
- "self_mute": false,
- "self_deaf": false,
- "suppress": false
- },
- "user": {
- "id": "190320984123768832",
- "username": "test 2",
- "discriminator": "7479",
- "avatar": "b004ec1740a63ca06ae2e14c5cee11f3",
- "bot": false
- },
- "nick": "test user 2",
- "mute": false,
- "volume": 110,
- "pan": {
- "left": 1.0,
- "right": 1.0
- }
- }
- ]
- },
- "nonce": "5d9df76d-6408-46a1-9368-33dca74fa423"
-}
-```
-
-#### GET_SELECTED_VOICE_CHANNEL
-
-Used to get the client's current voice channel. There are no arguments for this command. Returns the [Get Channel](/developers/docs/topics/rpc#getchannel) response, or `null` if none.
-
-#### SELECT_TEXT_CHANNEL
-
-Used to join and leave text channels, group dms, or dms. Returns the [Get Channel](/developers/docs/topics/rpc#getchannel) response, or `null` if none.
-
-###### Select Text Channel Argument Structure
-
-| Field | Type | Description |
-|------------|---------|-----------------------------------------------------------------|
-| channel_id | string | channel id to join (or `null` to leave) |
-| timeout | integer | asynchronously join channel with time to wait before timing out |
-
-#### GET_VOICE_SETTINGS
-
-###### Get Voice Settings Response Structure
-
-| Field | Type | Description |
-|------------------------|-----------------------------------------------------------------------------------------------------------|-----------------------------------|
-| input | [voice settings input](/developers/docs/topics/rpc#getvoicesettings-voice-settings-input-object) object | input settings |
-| output | [voice settings output](/developers/docs/topics/rpc#getvoicesettings-voice-settings-output-object) object | output settings |
-| mode | [voice settings mode](/developers/docs/topics/rpc#getvoicesettings-voice-settings-mode-object) object | voice mode settings |
-| automatic_gain_control | boolean | state of automatic gain control |
-| echo_cancellation | boolean | state of echo cancellation |
-| noise_suppression | boolean | state of noise suppression |
-| qos | boolean | state of voice quality of service |
-| silence_warning | boolean | state of silence warning notice |
-| deaf | boolean | state of self-deafen |
-| mute | boolean | state of self-mute |
-
-###### Voice Settings Input Object
-
-| Field | Type | Description |
-|-------------------|------------------|----------------------------------------------------------------------------|
-| device_id | string | device id |
-| volume | float | input voice level (min: 0, max: 100) |
-| available_devices | array of objects | array of _read-only_ device objects containing `id` and `name` string keys |
-
-###### Voice Settings Output Object
-
-| Field | Type | Description |
-|-------------------|------------------|----------------------------------------------------------------------------|
-| device_id | string | device id |
-| volume | float | output voice level (min: 0, max: 200) |
-| available_devices | array of objects | array of _read-only_ device objects containing `id` and `name` string keys |
-
-###### Voice Settings Mode Object
-
-| Field | Type | Description |
-|----------------|-----------------------------------------------------------------------------------------------------|---------------------------------------------------------------------|
-| type | string | voice setting mode type (can be `PUSH_TO_TALK` or `VOICE_ACTIVITY`) |
-| auto_threshold | boolean | voice activity threshold automatically sets its threshold |
-| threshold | float | threshold for voice activity (in dB) (min: -100, max: 0) |
-| shortcut | [shortcut key combo](/developers/docs/topics/rpc#getvoicesettings-shortcut-key-combo-object) object | shortcut key combos for PTT |
-| delay | float | the PTT release delay (in ms) (min: 0, max: 2000) |
-
-###### Shortcut Key Combo Object
-
-| Field | Type | Description |
-|-------|---------|-------------------------------------------------------------------------|
-| type | integer | see [key types](/developers/docs/topics/rpc#getvoicesettings-key-types) |
-| code | integer | key code |
-| name | string | key name |
-
-###### Key Types
-
-| Type | Id |
-|-----------------------|----|
-| KEYBOARD_KEY | 0 |
-| MOUSE_BUTTON | 1 |
-| KEYBOARD_MODIFIER_KEY | 2 |
-| GAMEPAD_BUTTON | 3 |
-
-###### Example Get Voice Settings Response Payload
-
-```json
-{
- "cmd": "GET_VOICE_SETTINGS",
- "data": {
- "input": {
- "available_devices": [
- {
- "id": "default",
- "name": "Default"
- },
- {
- "id": "Built-in Microphone",
- "name": "Built-in Microphone"
- }
- ],
- "device_id": "default",
- "volume": 49.803921580314636
- },
- "output": {
- "available_devices": [
- {
- "id": "default",
- "name": "Default"
- },
- {
- "id": "Built-in Output",
- "name": "Built-in Output"
- }
- ],
- "device_id": "default",
- "volume": 93.00000071525574
- },
- "mode": {
- "type": "VOICE_ACTIVITY",
- "auto_threshold": true,
- "threshold": -46.92622950819673,
- "shortcut": [{ "type": 0, "code": 12, "name": "i" }],
- "delay": 98.36065573770492
- },
- "automatic_gain_control": false,
- "echo_cancellation": false,
- "noise_suppression": false,
- "qos": false,
- "silence_warning": false,
- "deaf": false,
- "mute": false
- },
- "nonce": "fa07c532-bb03-4f75-8b9a-397f5109afb6"
-}
-```
-
-#### SET_VOICE_SETTINGS
-
-
-
-In the current release, we only support a single modifier of voice settings at a time over RPC. If an app changes voice settings, it will lock voice settings so that other apps connected simultaneously lose the ability to change voice settings. Settings reset to what they were before being changed after the controlling app disconnects. When an app that has previously set voice settings connects, the client will swap to that app's configured voice settings and lock voice settings again. This is a temporary situation that will be changed in the future.
-
-
-
-When setting voice settings, all fields are optional. Only passed fields are updated.
-
-###### Set Voice Settings Argument and Response Structure
-
-| Field | Type | Description |
-|------------------------|-----------------------------------------------------------------------------------------------------------|-----------------------------------|
-| input | [voice settings input](/developers/docs/topics/rpc#getvoicesettings-voice-settings-input-object) object | input settings |
-| output | [voice settings output](/developers/docs/topics/rpc#getvoicesettings-voice-settings-output-object) object | output settings |
-| mode | [voice settings mode](/developers/docs/topics/rpc#getvoicesettings-voice-settings-mode-object) object | voice mode settings |
-| automatic_gain_control | boolean | state of automatic gain control |
-| echo_cancellation | boolean | state of echo cancellation |
-| noise_suppression | boolean | state of noise suppression |
-| qos | boolean | state of voice quality of service |
-| silence_warning | boolean | state of silence warning notice |
-| deaf | boolean | state of self-deafen |
-| mute | boolean | state of self-mute |
-
-###### Example Set Voice Settings Command Payload
-
-```json
-{
- "nonce": "3d64ed55-ef6e-4bd5-99c9-677533babc22",
- "args": {
- "input": {
- "volume": 90.5
- }
- },
- "cmd": "SET_VOICE_SETTINGS"
-}
-```
-
-###### Example Set Voice Settings Response Payload
-
-```json
-{
- "cmd": "SET_VOICE_SETTINGS",
- "data": {
- "input": {
- "available_devices": [
- {
- "id": "default",
- "name": "Default"
- },
- {
- "id": "Built-in Microphone",
- "name": "Built-in Microphone"
- }
- ],
- "device_id": "default",
- "volume": 90.5
- },
- "output": {
- "available_devices": [
- {
- "id": "default",
- "name": "Default"
- },
- {
- "id": "Built-in Output",
- "name": "Built-in Output"
- }
- ],
- "device_id": "default",
- "volume": 93.00000071525574
- },
- "mode": {
- "type": "VOICE_ACTIVITY",
- "auto_threshold": true,
- "threshold": -46.92622950819673,
- "shortcut": [{ "type": 0, "code": 12, "name": "i" }],
- "delay": 98.36065573770492
- },
- "automatic_gain_control": false,
- "echo_cancellation": false,
- "noise_suppression": false,
- "qos": false,
- "silence_warning": false,
- "deaf": false,
- "mute": false
- },
- "nonce": "3d64ed55-ef6e-4bd5-99c9-677533babc22"
-}
-```
-
-#### SUBSCRIBE
-
-Used to subscribe to events. `evt` of the payload should be set to the event being subscribed to. `args` of the payload should be set to the args needed for the event.
-
-###### Subscribe Response Structure
-
-| Field | Type | Description |
-|-------|--------|------------------------------|
-| evt | string | event name now subscribed to |
-
-###### Example Subscribe Command Payload
-
-```json
-{
- "nonce": "be9a6de3-31d0-4767-a8e9-4818c5690015",
- "args": {
- "guild_id": "199737254929760256"
- },
- "evt": "GUILD_STATUS",
- "cmd": "SUBSCRIBE"
-}
-```
-
-###### Example Subscribe Response Payload
-
-```json
-{
- "cmd": "SUBSCRIBE",
- "data": {
- "evt": "GUILD_STATUS"
- },
- "nonce": "be9a6de3-31d0-4767-a8e9-4818c5690015"
-}
-```
-
-#### UNSUBSCRIBE
-
-Used to unsubscribe from events. `evt` of the payload should be set to the event that was subscribed to. `args` of the payload should be set to the args needed for the previously subscribed event.
-
-###### Unsubscribe Response Structure
-
-| Field | Type | Description |
-|-------|--------|----------------------------------|
-| evt | string | event name now unsubscribed from |
-
-###### Example Unsubscribe Command Payload
-
-```json
-{
- "nonce": "647d814a-4cf8-4fbb-948f-898aad24f55b",
- "args": {
- "guild_id": "199737254929760256"
- },
- "evt": "GUILD_STATUS",
- "cmd": "UNSUBSCRIBE"
-}
-```
-
-###### Example Unsubscribe Response Payload
-
-```json
-{
- "cmd": "UNSUBSCRIBE",
- "data": {
- "evt": "GUILD_STATUS"
- },
- "nonce": "647d814a-4cf8-4fbb-948f-898aad24f55b"
-}
-```
-
-#### SET_CERTIFIED_DEVICES
-
-Used by hardware manufacturers to send information about the current state of their certified devices that are connected to Discord.
-
-###### Set Certified Devices Argument Structure
-
-| Field | Type | Description |
-|---------|----------------------------------------------------------------------------------------------------|---------------------------------------------------------------|
-| devices | array of [certified device](/developers/docs/topics/rpc#setcertifieddevices-device-object) objects | a list of devices for your manufacturer, in order of priority |
-
-###### Device Object
-
-| Field | Type | Description |
-|---------------------------|--------------------------------------------------------------------------------|----------------------------------------------------------|
-| type | [device type](/developers/docs/topics/rpc#setcertifieddevices-device-type) | the type of device |
-| id | string | the device's Windows UUID |
-| vendor | [vendor](/developers/docs/topics/rpc#setcertifieddevices-vendor-object) object | the hardware vendor |
-| model | [model](/developers/docs/topics/rpc#setcertifieddevices-model-object) object | the model of the product |
-| related | array of strings | UUIDs of related devices |
-| echo_cancellation?\* | boolean | if the device's native echo cancellation is enabled |
-| noise_suppression?\* | boolean | if the device's native noise suppression is enabled |
-| automatic_gain_control?\* | boolean | if the device's native automatic gain control is enabled |
-| hardware_mute?\* | boolean | if the device is hardware muted |
-
-\*These fields are only applicable for `AUDIO_INPUT` device types
-
-###### Vendor Object
-
-| Field | Type | Description |
-|-------|--------|--------------------|
-| name | string | name of the vendor |
-| url | string | url for the vendor |
-
-###### Model Object
-
-| Field | Type | Description |
-|-------|--------|-------------------|
-| name | string | name of the model |
-| url | string | url for the model |
-
-###### Device Type
-
-| Type | Value |
-|--------------|---------------|
-| AUDIO_INPUT | "audioinput" |
-| AUDIO_OUTPUT | "audiooutput" |
-| VIDEO_INPUT | "videoinput" |
-
-###### Example Set Certified Devices Command Payload
-
-```json
-{
- "nonce": "9b4e9711-97f3-4f35-b047-32c82a51978e",
- "cmd": "SET_CERTIFIED_DEVICES",
- "args": {
- "devices": [
- {
- "type": "audioinput",
- "id": "aafc2003-da0e-42a3-b982-6a17a2812510",
- "vendor": {
- "name": "SteelSeries",
- "url": "https://steelseries.com"
- },
- "model": {
- "name": "Arctis 7",
- "url": "https://steelseries.com/gaming-headsets/arctis-7"
- },
- "related": ["aafc2003-da0e-42a3-b982-6a17a2819999"],
- "echo_cancellation": true,
- "noise_suppression": true,
- "automatic_gain_control": true,
- "hardware_mute": false
- }
- ]
- }
-}
-```
-
-###### Example Set Certified Devices Response Payload
-
-```json
-{
- "nonce": "9b4e9711-97f3-4f35-b047-32c82a51978e",
- "cmd": "SET_CERTIFIED_DEVICES",
- "data": null,
- "evt": null
-}
-```
-
-#### SET_ACTIVITY
-
-Used to update a user's Rich Presence.
-
-###### Set Activity Argument Structure
-
-
-When using `SET_ACTIVITY`, the `activity` object is limited to a `type` of Playing (`0`), Listening (`2`), Watching (`3`), or Competing (`5`).
-
-
-| Field | Type | Description |
-|----------|---------------------------------------------------------------------------|-----------------------------------------|
-| pid | integer | the application's process id |
-| activity | [activity](/developers/docs/events/gateway-events#activity-object) object | the rich presence to assign to the user |
-
-###### Example Set Activity Payload
-
-```json
-{
- "cmd": "SET_ACTIVITY",
- "args": {
- "pid": 9999,
- "activity": {
- "state": "In a Group",
- "state_url": "https://example.com/groups/50335231-9d9d-4ebd-873b-984787ee4d1d",
- "details": "Competitive | In a Match",
- "details_url": "https://example.com/matches/42340203-2f25-4534-8ff6-2a6509e81207",
- "timestamps": {
- "start": time(nullptr),
- "end": time(nullptr) + (60 * 5 + 23)
- },
- "assets": {
- "large_image": "numbani_map",
- "large_text": "Numbani",
- "large_url": "https://example.wiki/maps/Numbani",
- "small_image": "pharah_profile",
- "small_text": "Pharah",
- "small_url": "https://example.wiki/characters/Pharah"
- },
- "party": {
- "id": GameEngine.GetPartyId(),
- "size": [3, 6]
- },
- "secrets": {
- "join": "025ed05c71f639de8bfaa0d679d7c94b2fdce12f",
- "spectate": "e7eb30d2ee025ed05c71ea495f770b76454ee4e0",
- "match": "4b2fdce12f639de8bfa7e3591b71a0d679d7c93f"
- },
- "instance": true
- }
- },
- "nonce": "647d814a-4cf8-4fbb-948f-898abd24f55b"
-}
-```
-
-#### SEND_ACTIVITY_JOIN_INVITE
-
-Used to accept an Ask to Join request.
-
-###### Send Activity Join Invite Argument Structure
-
-| Field | Type | Description |
-|---------|-----------|-------------------------------|
-| user_id | snowflake | the id of the requesting user |
-
-###### Example Send Activity Join Invite Payload
-
-```json
-{
- "nonce": "5dc0c062-98c6-47a0-8922-15aerg126",
- "cmd": "SEND_ACTIVITY_JOIN_INVITE",
- "args": {
- "user_id": "53908232506183680"
- }
-}
-```
-
-#### CLOSE_ACTIVITY_REQUEST
-
-Used to reject an Ask to Join request.
-
-###### Close Activity Request Argument Structure
-
-| Field | Type | Description |
-|---------|-----------|-------------------------------|
-| user_id | snowflake | the id of the requesting user |
-
-###### Example Close Activity Request Payload
-
-```json
-{
- "nonce": "5dc0c062-98c6-47a0-8922-15aerg126",
- "cmd": "CLOSE_ACTIVITY_REQUEST",
- "args": {
- "user_id": "53908232506183680"
- }
-}
-```
-
-#### READY
-
-###### Ready Dispatch Data Structure
-
-| Field | Type | Description |
-|--------|------------------------------------------------------------------------------------------------------|------------------------------------|
-| v | integer | RPC version |
-| config | [rpc server configuration](/developers/docs/topics/rpc#ready-rpc-server-configuration-object) object | server configuration |
-| user | partial [user](/developers/docs/resources/user#user-object) object | the user to whom you are connected |
-
-###### RPC Server Configuration Object
-
-| Field | Type | Description |
-|--------------|--------|-----------------------|
-| cdn_host | string | server's cdn |
-| api_endpoint | string | server's api endpoint |
-| environment | string | server's environment |
-
-###### Example Ready Dispatch Payload
-
-```json
-{
- "cmd": "DISPATCH",
- "data": {
- "v": 1,
- "config": {
- "cdn_host": "cdn.discordapp.com",
- "api_endpoint": "//discord.com/api",
- "environment": "production"
- },
- "user": {
- "id": "53908232506183680",
- "username": "Mason",
- "discriminator": "1337",
- "avatar": null
- }
- },
- "evt": "READY"
-}
-```
-
-#### ERROR
-
-###### Error Data Structure
-
-| Field | Type | Description |
-|---------|---------|-------------------|
-| code | integer | RPC Error Code |
-| message | string | Error description |
-
-###### Example Error Payload
-
-```json
-{
- "cmd": "AUTHORIZE",
- "data": {
- "code": 4007,
- "message": "No client id provided"
- },
- "evt": "ERROR",
- "nonce": "5102b6f0-c769-4f37-8cca-25fb0ab22628"
-}
-```
-
-#### GUILD_STATUS
-
-###### Guild Status Argument Structure
-
-| Field | Type | Description |
-|----------|--------|-------------------------------------|
-| guild_id | string | id of guild to listen to updates of |
-
-###### Guild Status Dispatch Data Structure
-
-| Field | Type | Description |
-|--------|-----------------------------------------------------------------------|--------------------------------------------------------|
-| guild | partial [guild](/developers/docs/resources/guild#guild-object) object | guild with requested id |
-| online | integer | number of online users in guild (deprecated; always 0) |
-
-###### Example Guild Status Dispatch Payload
-
-```json
-{
- "cmd": "DISPATCH",
- "data": {
- "guild": {
- "id": "199737254929760256",
- "name": "test",
- "icon_url": null
- },
- "online": 0
- },
- "evt": "GUILD_STATUS"
-}
-```
-
-#### GUILD_CREATE
-
-No arguments
-
-###### Guild Create Dispatch Data Structure
-
-| Field | Type | Description |
-|-------|--------|-------------------|
-| id | string | guild id |
-| name | string | name of the guild |
-
-###### Example Guild Create Dispatch Payload
-
-```json
-{
- "cmd": "DISPATCH",
- "data": {
- "id": "199737254929767562",
- "name": "Test Server"
- },
- "evt": "GUILD_CREATE"
-}
-```
-
-#### CHANNEL_CREATE
-
-No arguments
-
-###### Channel Create Dispatch Data Structure
-
-| Field | Type | Description |
-|-------|---------|------------------------------------------------------------------|
-| id | string | channel id |
-| name | string | name of the channel |
-| type | integer | channel type (guild text: 0, guild voice: 2, dm: 1, group dm: 3) |
-
-###### Example Channel Create Dispatch Payload
-
-```json
-{
- "cmd": "DISPATCH",
- "data": {
- "id": "199737254929760257",
- "name": "General",
- "type": 0
- },
- "evt": "CHANNEL_CREATE"
-}
-```
-
-#### VOICE_CHANNEL_SELECT
-
-No arguments
-
-###### Voice Channel Select Dispatch Data Structure
-
-| Field | Type | Description |
-|------------|--------|--------------------------------|
-| channel_id | string | id of channel (`null` if none) |
-| guild_id | string | id of guild (`null` if none) |
-
-###### Example Voice Channel Select Dispatch Payload
-
-```json
-{
- "cmd": "DISPATCH",
- "data": {
- "channel_id": "199737254929760257",
- "guild_id": "199737254929760256"
- },
- "evt": "VOICE_CHANNEL_SELECT"
-}
-```
-
-#### VOICE_SETTINGS_UPDATE
-
-###### Voice Settings Argument Structure
-
-No arguments. Dispatches the [Get Voice Settings](/developers/docs/topics/rpc#getvoicesettings) response.
-
-###### Example Voice Settings Dispatch Payload
-
-```json
-{
- "cmd": "DISPATCH",
- "data": {
- "input": {
- "available_devices": [
- {
- "id": "default",
- "name": "Default"
- },
- {
- "id": "Built-in Microphone",
- "name": "Built-in Microphone"
- }
- ],
- "device_id": "default",
- "volume": 49.803921580314636
- },
- "output": {
- "available_devices": [
- {
- "id": "default",
- "name": "Default"
- },
- {
- "id": "Built-in Output",
- "name": "Built-in Output"
- }
- ],
- "device_id": "default",
- "volume": 93.00000071525574
- },
- "mode": {
- "type": "VOICE_ACTIVITY",
- "auto_threshold": true,
- "threshold": -46.92622950819673,
- "shortcut": [{ "type": 0, "code": 12, "name": "i" }],
- "delay": 98.36065573770492
- },
- "automatic_gain_control": false,
- "echo_cancellation": false,
- "noise_suppression": false,
- "qos": false,
- "silence_warning": false
- },
- "evt": "VOICE_SETTINGS_UPDATE"
-}
-```
-
-#### VOICE_STATE_CREATE/VOICE_STATE_UPDATE/VOICE_STATE_DELETE
-
-Dispatches channel voice state objects
-
-###### Voice State Argument Structure
-
-| Field | Type | Description |
-|------------|--------|---------------------------------------|
-| channel_id | string | id of channel to listen to updates of |
-
-###### Example Voice State Dispatch Payload
-
-```json
-{
- "cmd": "DISPATCH",
- "evt": "VOICE_STATE_CREATE",
- "data": {
- "voice_state": {
- "mute": false,
- "deaf": false,
- "self_mute": false,
- "self_deaf": false,
- "suppress": false
- },
- "user": {
- "id": "190320984123768832",
- "username": "test 2",
- "discriminator": "7479",
- "avatar": "b004ec1740a63ca06ae2e14c5cee11f3",
- "bot": false
- },
- "nick": "test user 2",
- "volume": 110,
- "mute": false,
- "pan": {
- "left": 1.0,
- "right": 1.0
- }
- }
-}
-```
-
-#### VOICE_CONNECTION_STATUS
-
-No arguments
-
-###### Voice Connection Status Dispatch Data Structure
-
-| Field | Type | Description |
-|--------------|-------------------|-------------------------------------------------|
-| state | string | one of the voice connection states listed below |
-| hostname | string | hostname of the connected voice server |
-| pings | array of integers | last 20 pings (in ms) |
-| average_ping | integer | average ping (in ms) |
-| last_ping | integer | last ping (in ms) |
-
-###### Voice Connection States
-
-| Field | Description |
-|--------------------|-----------------------------------|
-| DISCONNECTED | TCP disconnected |
-| AWAITING_ENDPOINT | Waiting for voice endpoint |
-| AUTHENTICATING | TCP authenticating |
-| CONNECTING | TCP connecting |
-| CONNECTED | TCP connected |
-| VOICE_DISCONNECTED | TCP connected, Voice disconnected |
-| VOICE_CONNECTING | TCP connected, Voice connecting |
-| VOICE_CONNECTED | TCP connected, Voice connected |
-| NO_ROUTE | No route to host |
-| ICE_CHECKING | WebRTC ice checking |
-
-###### Example Voice Connection Status Dispatch Payload
-
-```json
-{
- "cmd": "DISPATCH",
- "evt": "VOICE_CONNECTION_STATUS",
- "data": {
- "state": "VOICE_CONNECTED",
- "hostname": "some-server.discord.gg",
- "pings": [20, 13.37],
- "average_ping": 13.37,
- "last_ping": 20
- }
-}
-```
-
-#### MESSAGE_CREATE/MESSAGE_UPDATE/MESSAGE_DELETE
-
-Dispatches message objects, with the exception of deletions, which only contains the id in the message object.
-
-###### Message Argument Structure
-
-| Field | Type | Description |
-|------------|--------|---------------------------------------|
-| channel_id | string | id of channel to listen to updates of |
-
-###### Example Message Dispatch Payload
-
-```json
-{
- "cmd": "DISPATCH",
- "data": {
- "channel_id": "199737254929760256",
- "message": {
- "id": "199743874640379904",
- "blocked": false,
- "content": "test",
- "content_parsed": [
- {
- "content": "test",
- "type": "text"
- }
- ],
- "author_color": "#ffffff",
- "edited_timestamp": null,
- "timestamp": "2016-07-05T04:30:50.776Z",
- "tts": false,
- "mentions": [],
- "mention_roles": [],
- "mention_everyone": false,
- "embeds": [],
- "attachments": [],
- "type": 0,
- "pinned": false,
- "author": {
- "id": "190320984123768832",
- "username": "test user 2",
- "discriminator": "7479",
- "avatar": "b004ec1740a63ca06ae2e14c5cee11f3",
- "bot": false
- }
- }
- },
- "evt": "MESSAGE_CREATE"
-}
-```
-
-#### SPEAKING_START/SPEAKING_STOP
-
-###### Speaking Argument Structure
-
-| Field | Type | Description |
-|------------|--------|---------------------------------------|
-| channel_id | string | id of channel to listen to updates of |
-
-###### Speaking Dispatch Data Structure
-
-| Field | Type | Description |
-|---------|--------|-----------------------------------------|
-| user_id | string | id of user who started/stopped speaking |
-
-###### Example Speaking Dispatch Payload
-
-```json
-{
- "cmd": "DISPATCH",
- "data": {
- "user_id": "190320984123768832"
- },
- "evt": "SPEAKING_STOP"
-}
-```
-
-#### NOTIFICATION_CREATE
-
-No arguments. This event requires the `rpc.notifications.read` [OAuth2 scope](/developers/docs/topics/oauth2#shared-resources-oauth2-scopes).
-
-###### Notification Create Dispatch Data Structure
-
-| Field | Type | Description |
-|------------|---------------------------------------------------------------------|-------------------------------------------|
-| channel_id | string | id of channel where notification occurred |
-| message | [message](/developers/docs/resources/message#message-object) object | message that generated this notification |
-| icon_url | string | icon url of the notification |
-| title | string | title of the notification |
-| body | string | body of the notification |
-
-###### Example Notification Create Dispatch Payload
-
-```json
-{
- "cmd": "DISPATCH",
- "data": {
- "channel_id": "199737254929760256",
- "message": {
- "id": "199743874640379904",
- "blocked": false,
- "content": "test",
- "content_parsed": [
- {
- "content": "test",
- "type": "text"
- }
- ],
- "author_color": "#ffffff",
- "edited_timestamp": null,
- "timestamp": "2016-07-05T04:30:50.776Z",
- "tts": false,
- "mentions": [],
- "mention_roles": [],
- "mention_everyone": false,
- "embeds": [],
- "attachments": [],
- "type": 0,
- "pinned": false,
- "author": {
- "id": "190320984123768832",
- "username": "test user 2",
- "discriminator": "7479",
- "avatar": "b004ec1740a63ca06ae2e14c5cee11f3",
- "bot": false
- }
- },
- "icon_url": "https://cdn.discordapp.com/avatars/155607406007681024/8ab559b8286e48270c04471ae382cd9d.jpg",
- "title": "test_user (#general)",
- "body": "test message"
- },
- "evt": "NOTIFICATION_CREATE"
-}
-```
-
-#### ACTIVITY_JOIN
-
-No arguments
-
-###### Activity Join Dispatch Data Structure
-
-| Field | Type | Description |
-|--------|--------|------------------------------------------------------------------------------------------------------------|
-| secret | string | the [`join_secret`](/developers/docs/developer-tools/game-sdk#activitysecrets-struct) for the given invite |
-
-###### Example Activity Join Dispatch Payload
-
-```json
-{
- "cmd": "DISPATCH",
- "data": {
- "secret": "025ed05c71f639de8bfaa0d679d7c94b2fdce12f"
- },
- "evt": "ACTIVITY_JOIN"
-}
-```
-
-#### ACTIVITY_SPECTATE
-
-No arguments
-
-###### Activity Spectate Dispatch Data Structure
-
-| Field | Type | Description |
-|--------|--------|----------------------------------------------------------------------------------------------------------------|
-| secret | string | the [`spectate_secret`](/developers/docs/developer-tools/game-sdk#activitysecrets-struct) for the given invite |
-
-###### Example Activity Spectate Dispatch Payload
-
-```json
-{
- "cmd": "DISPATCH",
- "data": {
- "secret": "e7eb30d2ee025ed05c71ea495f770b76454ee4e0"
- },
- "evt": "ACTIVITY_SPECTATE"
-}
-```
-
-#### ACTIVITY_JOIN_REQUEST
-
-No arguments
-
-###### Activity Join Request Data Structure
-
-| Field | Type | Description |
-|-------|--------------------------------------------------------------------|-----------------------------------------------|
-| user | partial [user](/developers/docs/resources/user#user-object) object | information about the user requesting to join |
-
-###### Example Activity Join Request Dispatch Payload
-
-```json
-{
- "cmd": "DISPATCH",
- "data": {
- "user": {
- "id": "53908232506183680",
- "username": "Mason",
- "discriminator": "1337",
- "avatar": "a_bab14f271d565501444b2ca3be944b25"
- }
- },
- "evt": "ACTIVITY_JOIN_REQUEST"
-}
-```
diff --git a/discord/developers/docs/topics/teams.md b/discord/developers/docs/topics/teams.md
deleted file mode 100644
index 0d69eb54c7..0000000000
--- a/discord/developers/docs/topics/teams.md
+++ /dev/null
@@ -1,82 +0,0 @@
-# Teams
-
-Teams are groups of developers (or other Discord users) who want to collaborate and share access to an app's configuration, management, and payout settings. Go team(s)!
-
-## Creating a Team
-
-To create or be a member on a team, you must [enable 2FA for your Discord account](https://support.discord.com/hc/en-us/articles/219576828-Setting-up-Two-Factor-Authentication). After you have 2FA enabled, create a team by navigating to the [Teams page](https://discord.com/developers/teams) then clicking the "New Team" button.
-
-
-
-Once you create a team, you'll land on the **Team Information** page where you can fill out details and start inviting other Discord users to join your team. Since users added to a team have access to any apps that team owns, use caution when adding new team members.
-
-
-
-Only the team Owner and team Admins can invite or remove additional users.
-
-
-
-## Adding Apps to a Team
-
-Once your team is set up, you can create or transfer apps that will be owned by the team. Teams can have a maximum of 25 apps.
-
-### Creating an App
-
-To create a new app that belongs to a team, select the team from the **Team** dropdown in the app creation modal. If you want to keep the app under your own account's ownership, choose `Personal`:
-
-
-
-### Transferring an App
-
-To transfer an existing app to a team, navigate to the [Application](https://discord.com/developers/applications) that you want to transfer. At the bottom of the app's **General Information** page, click "Transfer App to Team".
-
-
-
-Once an app has been transferred to a team, it _cannot_ be transferred back.
-
-
-
-
-
-## Team Member Roles
-
-Team members can be one of four roles (owner, admin, developer, and read-only), and each role inherits the access of those below it. Roles for team members can be configured under **Team Members** in a team's settings.
-
-###### Team Member Role Types
-
-| Role Name | Value | Description |
-|-----------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Owner\* | | Owners are the most permissible role, and can take destructive, irreversible actions like deleting team-owned apps or the team itself. Teams are limited to 1 owner. |
-| Admin | admin | Admins have similar access as owners, except they cannot take destructive actions on the team or team-owned apps. |
-| Developer | developer | Developers can access information about team-owned apps, like the client secret or public key. They can also take limited actions on team-owned apps, like configuring interaction endpoints or resetting the bot token. Members with the Developer role *cannot* manage the team or its members, or take destructive actions on team-owned apps. |
-| Read-only | read_only | Read-only members can access information about a team and any team-owned apps. Some examples include getting the IDs of applications and exporting payout records. Members can also invite bots associated with team-owned apps that are marked private. |
-
-\* The owner role is not represented in the `role` field on the [team member object](/developers/docs/topics/teams#data-models-team-member-object). Instead, the `owner_user_id` field on the [team object](/developers/docs/topics/teams#data-models-team-object) should be used to identify which user has the owner role for the team.
-
-## Data Models
-
-###### Team Object
-
-| field | type | description |
-|---------------|----------------------------------------------------------------------------------------------|--------------------------------------|
-| icon | ?string | Hash of the image of the team's icon |
-| id | snowflake | Unique ID of the team |
-| members | array of [team member](/developers/docs/topics/teams#data-models-team-member-object) objects | Members of the team |
-| name | string | Name of the team |
-| owner_user_id | snowflake | User ID of the current team owner |
-
-###### Team Member Object
-
-| field | type | description |
-|------------------|--------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------|
-| membership_state | integer | User's [membership state](/developers/docs/topics/teams#data-models-membership-state-enum) on the team |
-| team_id | snowflake | ID of the parent team of which they are a member |
-| user | partial [user](/developers/docs/resources/user#user-object) object | Avatar, discriminator, ID, and username of the user |
-| role | string | [Role](/developers/docs/topics/teams#team-member-roles-team-member-role-types) of the team member |
-
-###### Membership State Enum
-
-| name | value |
-|----------|-------|
-| INVITED | 1 |
-| ACCEPTED | 2 |
diff --git a/discord/developers/docs/topics/threads.md b/discord/developers/docs/topics/threads.md
deleted file mode 100644
index 1c323454c8..0000000000
--- a/discord/developers/docs/topics/threads.md
+++ /dev/null
@@ -1,253 +0,0 @@
-# Threads
-
-[Threads](/developers/docs/resources/channel#channel-object) can be thought of as temporary sub-channels inside an existing channel, to help better organize conversation in a busy channel.
-
-Threads have been designed to be very similar to [channel](/developers/docs/resources/channel#channel-object) objects, and this topic aggregates all of the information about threads, which should all help to make migrating very straightforward.
-
-## Backwards Compatibility
-
-Threads are only available in API v9 and above. Bots that do not update to API v9 or above will not receive most gateway events for threads, or things that happen in threads (such as [Message Create](/developers/docs/events/gateway-events#message-create)). Bots on API v8 will still receive gateway events for Interactions.
-
-The list of gateway events that may be dropped includes, but is not limited to:
-
-- MESSAGE_CREATE
-- MESSAGE_DELETE
-- MESSAGE_DELETE_BULK
-- MESSAGE_REACTION_ADD
-- MESSAGE_REACTION_REMOVE
-- MESSAGE_REACTION_REMOVE_ALL
-- MESSAGE_REACTION_REMOVE_EMOJI
-- MESSAGE_UPDATE
-- THREAD_CREATE
-- THREAD_UPDATE
-- THREAD_DELETE
-- THREAD_MEMBER_UPDATE
-- THREAD_MEMBERS_UPDATE
-
-## Thread Fields
-
-Threads share and repurpose a number of the existing fields from the [channel object](/developers/docs/resources/channel#channel-object):
-
-- `id`, `guild_id`, `type`, `name`, `last_message_id`, `last_pin_timestamp`, `rate_limit_per_user` and `flags` are being re-used
-- `owner_id` has been repurposed to store the id of the user that started the thread
-- `parent_id` has been repurposed to store the id of the `GUILD_TEXT` or `GUILD_ANNOUNCEMENT` channel the thread was created in
-
-Additionally, there are a few fields that are only available on threads:
-
-- `member_count` stores an approximate member count, but it stops counting at 50 (this is only used in our UI, so it is not valuable to bots)
-- `message_count` and `total_message_sent` store the number of messages in a thread. The difference is that when a message is deleted, `message_count` is decremented, but `total_message_sent` will not be. (threads created before July 1, 2022 stop counting both values at 50).
-- `thread_metadata` contains a few thread specific fields, `archived`, `archive_timestamp`, `auto_archive_duration`, `locked`. `archive_timestamp` is changed when creating, archiving, or unarchiving a thread, and when changing the `auto_archive_duration` field.
-
-## Public & Private Threads
-
-Public threads are viewable by everyone who can view the parent channel of the thread. Public threads must be created from an existing message, but can be "orphaned" if that message is deleted. The created thread and the message it was started from will share the same id. The [type](/developers/docs/resources/channel#channel-object-channel-types) of thread created matches the [type](/developers/docs/resources/channel#channel-object-channel-types) of the parent channel. `GUILD_TEXT` channels [create](/developers/docs/resources/channel#start-thread-from-message) `PUBLIC_THREAD` and `GUILD_ANNOUNCEMENT` channels [create](/developers/docs/resources/channel#start-thread-from-message) `ANNOUNCEMENT_THREAD`.
-
-Private threads behave similar to Group DMs, but in a Guild. Private threads are always [created](/developers/docs/resources/channel#start-thread-without-message) with the `GUILD_PRIVATE_THREAD` [type](/developers/docs/resources/channel#channel-object-channel-types) and can only be created in `GUILD_TEXT` channels.
-
-## Locked Threads
-Users (including bot users) without the `MANAGE_THREADS` permission are more restricted in locked threads. Users won't be able to create or update messages in locked threads, or update properties like its title or tags. Additionally, some user activity like deleting messages and adding or removing reactions will *only* be allowed in locked threads if that thread is also active (or un-archived).
-
-If a user or bot user has the `MANAGE_THREADS` permission, they will still be able to make changes to the thread and messages.
-
-## Active & Archived Threads
-
-Every thread can be either active or archived. Changing a thread from archived -> active is referred to as unarchiving the thread. Threads that have `locked` set to true can only be unarchived by a user with the `MANAGE_THREADS` permission.
-
-Besides helping to de-clutter the UI for users, archiving exists to limit the working set of threads that need to be kept around. Since the number of archived threads can be quite large, keeping all of them in memory may be quite prohibitive. Therefore guilds are capped at a certain number of active threads, and only active threads can be manipulated. Users cannot edit messages, add reactions, use application commands, or join archived threads. The only operation that should happen within an archived thread is messages being deleted. Sending a message will automatically unarchive the thread, unless the thread has been locked by a moderator.
-
-Because of this constraint, the gateway protocol is designed to ensure that bots are able to have an accurate view of the full set of active threads, but archived threads are not synced up-front via the gateway.
-
-Threads do not count against the max-channels limit in a guild, but there is a limit on the maximum number of active threads in a guild.
-
-Threads automatically archive after a period of inactivity. As a server approaches the max thread limit this timer will automatically lower, usually not below the `auto_archive_duration`. In very busy channels, threads set to a 7 day auto archive may archive earlier to help avoid the server becoming "full"). "Activity" is defined as sending a message, unarchiving a thread, or changing the auto-archive time. The `auto_archive_duration` field previously controlled how long a thread could stay active, but is now repurposed to control how long the thread stays in the channel list. Channels can also set `default_auto_archive_duration`, which is used by our clients to pre-select a different `auto_archive_duration` value when a user creates a thread.
-
-## Permissions
-
-Threads generally inherit permissions from the parent channel (e.g. if you can add reactions in the parent channel, you can do that in a thread as well).
-
-Three permission bits are specific to threads: `CREATE_PUBLIC_THREADS`, `CREATE_PRIVATE_THREADS`, and `SEND_MESSAGES_IN_THREADS`.
-
-
-
-The `SEND_MESSAGES` permission has no effect in threads; users must have `SEND_MESSAGES_IN_THREADS` to talk in a thread.
-
-
-
-Private threads are similar to Group DMs, but in a guild: You must be invited to the thread to be able to view or participate in it, or be a moderator (`MANAGE_THREADS` permission).
-
-Finally, threads are treated slightly differently from channels in the gateway protocol. Clients will not be informed of a thread through the gateway if they do not have permission to view that thread.
-
-## Gateway Events
-
-- [Guild Create](/developers/docs/events/gateway-events#guild-create) contains a field, `threads`, which is an array of channel objects. This represents all active threads in the guild that the current user is able to view.
-- When a thread is created, updated, or deleted, a [Thread Create](/developers/docs/events/gateway-events#thread-create), [Thread Update](/developers/docs/events/gateway-events#thread-update), or [Thread Delete](/developers/docs/events/gateway-events#thread-delete) event is sent. Like their channel counterparts, these just contain a thread.
-- Since the gateway only syncs active threads that the user can see, if a user _gains_ access to a channel, then the gateway may need to sync the active threads in that channel to the user. It will send a [Thread List Sync](/developers/docs/events/gateway-events#thread-list-sync) event for this.
-
-## Thread Membership
-
-Each thread tracks explicit membership. There are two primary use cases for this data:
-
-- Clients use _their own_ [thread member](/developers/docs/resources/channel#thread-member-object) to calculate read states and notification settings. This is largely irrelevant for bots though, but is the reason for some of the syncing complexity detailed here.
-- Knowing everyone that is in a thread.
-
-Membership is tracked in an array of [thread member](/developers/docs/resources/channel#thread-member-object) objects. These have four fields, `id` (the thread id), `user_id`, `join_timestamp`, and `flags`. Currently the only `flags` are for notification settings, but others may be added in future updates.
-
-### Syncing for the current user
-
-- A [Thread Members Update](/developers/docs/events/gateway-events#thread-members-update) Gateway Event is always sent when the current user is added to or removed from a thread.
-- A [Thread Member Update](/developers/docs/events/gateway-events#thread-member-update) Gateway Event is sent whenever the current user's [thread member](/developers/docs/resources/channel#thread-member-object) object is updated.
-- Certain API calls, such as listing archived threads and search will return an array of [thread member](/developers/docs/resources/channel#thread-member-object) objects for any returned threads the current user is a member of. Other API calls, such as getting a channel will return the [thread member](/developers/docs/resources/channel#thread-member-object) object for the current user as a property on the channel, if the current user is a member of the thread.
-- The [Guild Create](/developers/docs/events/gateway-events#guild-create) Gateway Event will contain a [thread member](/developers/docs/resources/channel#thread-member-object) object as a property on any returned threads the current is a member of.
-- The [Thread Create](/developers/docs/events/gateway-events#thread-create) Gateway Event will contain a [thread member](/developers/docs/resources/channel#thread-member-object) object as a property of the thread if the current user is a member of, and the user has recently gained access to view the parent channel.
-- The [Thread List Sync](/developers/docs/events/gateway-events#thread-list-sync) Gateway Event will contain an array of [thread member](/developers/docs/resources/channel#thread-member-object) objects for any returned threads the current user is a member of.
-
-### Syncing for other users
-
-
-These require the `GUILD_MEMBERS` [Gateway Intent](/developers/docs/events/gateway#gateway-intents)
-
-
-- An API `GET` call to [`/channels//thread-members`](/developers/docs/resources/channel#list-thread-members) which returns an array of [thread member](/developers/docs/resources/channel#thread-member-object) objects.
-- The [Thread Members Update](/developers/docs/events/gateway-events#thread-members-update) Gateway Event which will include all users who were added to or removed from a thread by an action.
-
-## Editing & Deleting Threads
-
-Threads can be edited and deleted with the existing `PATCH` and `DELETE` endpoints to edit a channel.
-
-- Deleting a thread requires the `MANAGE_THREADS` permission.
-- Editing a thread to set `archived` to `false` only requires the current user has already been added to the thread. If `locked` is true, then the user must have created the thread or have `MANAGE_THREADS`
-- Editing a thread to change the `name`, `archived`, `auto_archive_duration` fields requires `MANAGE_THREADS` or that the current user is the thread creator
-- Editing a thread to change `rate_limit_per_user` or `locked` requires `MANAGE_THREADS`
-
-## NSFW Threads
-
-Threads do not explicitly set the `nsfw` field. All threads in a channel marked as `nsfw` inherit that setting though.
-
-## New Message Types
-
-Threads introduce a few [message types](/developers/docs/resources/message#message-object-message-types), and repurpose some others:
-
-- `RECIPIENT_ADD` and `RECIPIENT_REMOVE` have been repurposed to also send when a user is added to or removed from a thread by someone else
-- `CHANNEL_NAME_CHANGE` has been repurposed and is sent when the thread's name is changed
-- `THREAD_CREATED` is a new message sent to the parent `GUILD_TEXT` channel, used to inform users that a thread has been created. It is currently only sent in one case: when a `PUBLIC_THREAD` is created from an older message (older is still TBD, but is currently set to a very small value). The message contains a [message reference](/developers/docs/resources/message#message-reference-structure) with the `guild_id` and `channel_id` of the thread. The `content` of the message is the `name` of the thread.
-- `THREAD_STARTER_MESSAGE` is a new message sent as the first message in threads that are started from an existing message in the parent channel. It _only_ contains a [message reference](/developers/docs/resources/message#message-reference-structure) field that points to the message from which the thread was started.
-
-## Enumerating threads
-
-There are four `GET` routes for enumerating threads in a specific channel:
-
-- [`/guilds//threads/active`](/developers/docs/resources/guild#list-active-guild-threads) returns all active threads in a guild that the current user can access, includes public & private threads
-- [`/channels//users/@me/threads/archived/private`](/developers/docs/resources/channel#list-joined-private-archived-threads) returns all archived, private threads in a channel, that the current user has is a member of, sorted by thread id descending
-- [`/channels//threads/archived/public`](/developers/docs/resources/channel#list-public-archived-threads) returns all archived, public threads in a channel, sorted by archive timestamp descending
-- [`/channels//threads/archived/private`](/developers/docs/resources/channel#list-private-archived-threads) returns all archived, private threads in a channel, sorted by archive timestamp descending
-
-## Webhooks
-
-Webhooks can send messages to threads by using the `thread_id` query parameter. See the [execute webhook](/developers/docs/resources/webhook#execute-webhook) docs for more details.
-
-## Details about Thread Access and Syncing
-
-While the syncing of threads is similar to channels, there are two important differences that are relevant for [Thread List Sync](/developers/docs/events/gateway-events#thread-list-sync) and [Thread Create](/developers/docs/events/gateway-events#thread-create) events:
-
-1. The [Gateway](/developers/docs/events/gateway) will only sync threads that the app has permission to view
-2. The Gateway will only sync threads once the app has "subscribed" to the guild. For context, in Discord's official clients, a subscription happens when the user visits a channel in the guild.
-
-These differences mean there is some unique behavior that is worth going into.
-
-### Thread Access
-
-#### Gaining Access to Private Threads
-
-When an app is added to a private thread, it likely doesn't have that thread in memory yet since it doesn't have permission to view it.
-
-Private threads are only synced to you if you are a member or a moderator. Whenever a user is added to a private thread, the Gateway also sends a [Thread Create](/developers/docs/events/gateway-events#thread-create) event. This ensures the client always has a non-null value for that thread.
-
-
-The `THREAD_CREATE` event is also sent when the user is a moderator (and thus would already have the channel in memory).
-
-
-#### Gaining Access to Public Threads
-
-Upon connecting to the Gateway, apps will be automatically subscribed to thread events and active threads.
-
-However, when a non-app is added to a public thread but hasn't subscribed to threads, it may not have that thread in memory yet (which is a requirement for Discord's clients). Because of this, the Gateway will send a [Thread Create](/developers/docs/events/gateway-events#thread-create) event when a user is added to _any_ thread, even if the event is not necessary for apps.
-
-### Channel Access
-
-#### Gaining Access to Channels
-
-When an app gains access to a channel (for example, they're given the moderator role), they likely won't have the threads in memory for that channel since the Gateway only syncs threads that the client has permission to view. To account for this, a [Thread List Sync](/developers/docs/events/gateway-events#thread-list-sync) event is sent.
-
-The [Thread List Sync](/developers/docs/events/gateway-events#thread-list-sync) event contains a `channel_ids` array, which is the IDs of all channels whose threads are being synced. This field can be used to first clear out any active threads whose `parent_id` is in the `channel_ids` array, and then ingest any threads that were in the event.
-
-#### Losing Access to Channels
-
-When an app loses access to a channel, the Gateway does **not** send it [Thread Delete](/developers/docs/events/gateway-events#thread-delete) event (or any equivalent thread-specific event). Instead, the app will receive the event that caused its permissions on the channel to change.
-
-If an app wanted to track when it lost access to any thread, it's possible but difficult as it would need to handle all cases correctly. Usually, events that cause permission changes are a [Guild Role Update](/developers/docs/events/gateway-events#guild-role-update), [Guild Member Update](/developers/docs/events/gateway-events#guild-member-update) or [Channel Update](/developers/docs/events/gateway-events#channel-update) event.
-
-
-Discord's clients check their permissions *first* when performing an action. That way, even if it has some stale data, it does not end up acting on it.
-
-
-Additionally, when a user or app loses access to a channel, they are not removed from the thread and will continue to be reported as a member of that thread. However, they will **not** receive any new Gateway events unless they are removed from the thread, in which case they will receive a [Thread Members Update](/developers/docs/events/gateway-events#thread-members-update) event.
-
-### Unarchiving a Thread
-
-When a thread is unarchived, there is no guarantee that an app has the thread or its member status in memory. To account for this, the Gateway will send two events (in the listed order):
-
-1. A [Thread Update](/developers/docs/events/gateway-events#thread-update) event, which contains the full channel object.
-2. A [Thread Member Update](/developers/docs/events/gateway-events#thread-member-update) event, which is sent to all members of the unarchived thread. Discord's clients only load active threads into memory on start, so this event is sent even if it may not be relevant to most apps.
-
-## Forums
-
-A `GUILD_FORUM` (type `15`) channel is similar to a `GUILD_TEXT` channel, except *only* threads can be created in them. Unless otherwise noted, threads in forum channels behave in the same way as in text channels—meaning they use the same endpoints and receive the same Gateway events.
-
-Messages cannot be sent directly in forum channels.
-
-
-
-More information about forum channels and how they appear in Discord can be found in the [Forum Channels FAQ](https://support.discord.com/hc/en-us/articles/6208479917079-Forum-Channels-FAQ#h_01G69FJQWTWN88HFEHK7Z6X79N)
-
-
-
-## Media Channels
-
-A `GUILD_MEDIA` (type `16`) channel is similar to a `GUILD_FORUM` channel in that only threads can be created in them. Unless otherwise noted, threads in media channels behave in the same way as in forum channels - meaning they use the same endpoints and receive the same Gateway events. More information about media channels and how they appear in Discord can be found in the [media channels Help Center Article](https://creator-support.discord.com/hc/en-us/articles/14346342766743).
-
-
-
-`GUILD_MEDIA` channels are in beta and still being actively developed. The API and other technical details are subject to change.
-
-
-
-
-### Creating Threads in Forum and Media Channels
-
-Within thread-only channels, threads appear as posts. Threads can be created using the [`POST /channels//threads`](/developers/docs/resources/channel#start-thread-in-forum-or-media-channel) endpoint with [slightly different parameters](/developers/docs/resources/channel#start-thread-in-forum-or-media-channel-jsonform-params) than threads in text channels. For example, when creating threads in a threads-only channel, a message is created that has the same ID as the thread which requires you to pass parameters for both a thread *and* a message.
-
-Threads in thread-only channels have the same permissions behavior as threads in a text channel, inheriting all permissions from the parent channel, with one exception: creating a thread in a thread-only channel only requires the `SEND_MESSAGES` permission.
-
-### Forum and Media Channel Fields
-
-It's worth calling out a few details about fields specific to thread-only channels that may be important to keep in mind:
-
-- The `last_message_id` field is the ID of the most recently created thread in that channel. As with messages, your app will not receive a `CHANNEL_UPDATE` event when the field is changed. Instead clients should update the value when receiving [Thread Create](/developers/docs/events/gateway-events#thread-create) events.
-- The `topic` field is what is shown in the "Guidelines" section within the Discord client.
-- The `rate_limit_per_user` field limits how frequently threads can be created. There is a new `default_thread_rate_limit_per_user` field on thread-only channels as well, which limits how often messages can be sent _in a thread_. This field is copied into `rate_limit_per_user` on the thread at creation time.
-- The `available_tags` field can be set when creating or updating a channel, which determines which tags can be set on individual threads within the thread's `applied_tags` field.
-- The `flags` field indicates any [channel flags](/developers/docs/resources/channel#channel-object-channel-flags) set for a thread-only channel. Currently only `REQUIRE_TAG` can be used, which requires that a tag from `available_tags` be specified when creating a thread in that channel.
-
-All fields for channels, including thread-only channels, can be found in the [Channel Object](/developers/docs/resources/channel#channel-object).
-
-### Forum and Media Channel Thread Fields
-
-A thread can be pinned within a thread-only, which will be represented as the [`PINNED` flag](/developers/docs/resources/channel#channel-object-channel-flags) in the `flags` field within a thread-only channel. A thread that is pinned will have the `(1 << 1)` flag set, and archiving that thread will unset the flag. A pinned thread will *not* auto-archive.
-
-The `message_count` and `total_message_sent` fields on threads in thread-only channels will increment on `MESSAGE_CREATE` events, and decrement on `MESSAGE_DELETE` and `MESSAGE_DELETE_BULK` events. There will be no specific `CHANNEL_UPDATE` event that notifies your app of changes to those fields—instead, apps should update those values when receiving corresponding events.
-
-All fields for threads in thread-only channels can be found in the [channel resources documentation](/developers/docs/resources/channel#start-thread-in-forum-or-media-channel-jsonform-params).
-
-### Forum and Media Channel Formatting
-
-In thread-only channels, the first message in a thread and the channel topic can both contain markdown for bulleted lists and headings (unlike text channels).
diff --git a/discord/developers/docs/tutorials/configuring-app-metadata-for-linked-roles.md b/discord/developers/docs/tutorials/configuring-app-metadata-for-linked-roles.md
deleted file mode 100644
index 9152021d17..0000000000
--- a/discord/developers/docs/tutorials/configuring-app-metadata-for-linked-roles.md
+++ /dev/null
@@ -1,198 +0,0 @@
-# Configuring App Metadata for Linked Roles
-
-Linked roles are a type of role in Discord that requires a user to connect to 3rd-party services and meet defined criteria. A role's criteria could just include the user connecting to that service, but it's often more narrow—like having a verified account, having certain stats, or having more than a certain number of followers.
-
-Apps can define their own [role connection metadata](/developers/docs/resources/application-role-connection-metadata), which admins can use to configure linked roles in servers where that app is installed. Apps must also set up an [OAuth2 flow](/developers/docs/topics/oauth2) to allow users to authenticate and grant the required `role_connections.write` scope.
-
-This tutorial walks through building a Discord app in JavaScript with linked roles support.
-
-
-This tutorial was originally written for Glitch, which is no longer available. We're currently updating this tutorial to use a different hosting platform.
-
-
-
-All of the sample code used in this tutorial can be found in the [`linked-roles-sample` GitHub repo](https://github.com/discord/linked-roles-sample)
-
-
----
-
-## Creating an app
-
-The first thing we’ll do is create an app through the [developer dashboard](https://discord.com/developers/applications). If you already have an app created, you can jump right to the [Running your app](/developers/docs/tutorials/configuring-app-metadata-for-linked-roles#running-your-app) section.
-
-
-Basic steps to create an app are outlined below, but a more detailed walkthrough is in the [Getting Started guide](/developers/docs/quick-start/getting-started).
-
-
-- Navigate to the [developer dashboard](https://discord.com/developers/applications)
-- Click **New Application** in the upper right corner, then select a name and create your app
-- Click on the **Bot** tab on the left sidebar. On that page, click **Reset Token** and store the token somewhere safe (like in a password manager)
-
-
-
-Bot tokens are used to authorize API requests and carry your bot's permissions, making them highly sensitive. Never share your token or check it into any kind of version control.
-
-
-
-### Adding scopes
-
-Apps need approval from installing users to perform actions inside of Discord. So before installing your app, let's add some scopes to request during installation.
-
-- Click on `OAuth2` in the left sidebar, then `URL generator`
-- Check the `bot` scope
-- After the scope is selected, you should see a **Generated URL** which can be used to install your app
-
-
-See a list of all [OAuth2 scopes](/developers/docs/topics/oauth2#shared-resources-oauth2-scopes), or read more on [user permissions](/developers/docs/topics/permissions) in the documentation.
-
-
-### Installing your app
-
-Copy the **Generated URL** from above, and paste it into your browser. You’ll be guided through the installation flow, where you should make sure you’re installing the app on a server where you can develop and test.
-
-After installing your app, you can head over to your server and see that it has joined ✨
-
-## Running your app
-
-All of the code used in the example app can be found in the [GitHub repository](https://github.com/discord/linked-roles-sample).
-
-### Remix the project
-
-This guide uses Glitch, which allows you to quickly clone and develop an app from within your browser. There are also instructions on developing locally using ngrok in the README if you'd prefer.
-
-
-
-While Glitch is great for development and testing, [it has technical limitations](https://help.glitch.com/kb/article/17-technical-restrictions/) so other hosting providers should be considered for production apps.
-
-
-
-To start, [remix (or clone) the Glitch project 🎏](https://glitch.com/edit/#!/remix/linked-role-discord-bot)
-
-When you remix the project, you'll see a new Glitch project with a unique name similar to this:
-
-
-
-#### Project structure
-
-All of the files for the project are on the left-hand side. Here's a quick glimpse at the structure:
-
-```
-├── assets -> images used in this tutorial
-├── src
-│ ├── config.js -> Parsing of local configuration
-│ ├── discord.js -> Discord specific auth & API wrapper
-│ ├── register.js -> Tool to register the metadata schema
-│ ├── server.js -> Main entry point for the application
-│ ├── storage.js -> Provider for storing OAuth2 tokens
-├── .env -> your credentials and IDs
-├── .gitignore
-├── package.json
-└── README.md
-```
-
-### Configure your app
-
-There's already some code in your `server.js` file, but you’ll need your app’s token and ID to make requests. All of your credentials can be stored directly in the `.env` file.
-
-
-
-It bears repeating that you should never check any credentials or secrets into source control. The getting started project's `.gitignore` comes pre-loaded with `.env` to prevent it.
-
-
-
-First, copy your bot user’s token from earlier and paste it in the `DISCORD_TOKEN` variable in your `.env` file.
-
-Next, navigate to your app settings in the developer portal, and navigate to OAuth2 -> General. Copy the Client ID and Client Secret for your application, and paste the values as `DISCORD_CLIENT_ID` and `DISCORD_CLIENT_SECRET` in your `.env`.
-
-
-
-Now, we need to set the Redirect URL that will be used for our OAuth2 flow. Go back to Glitch, and click the `Share` button for your project. Copy the public live URL for your app:
-
-
-
-Go back to the OAuth2 -> General tab in the Discord developer portal, and add a new redirect for your app using the Glitch URL and the `/discord-oauth-callback` route. Copy this URL, then paste it as `DISCORD_REDIRECT_URI` in your `.env`.
-
-Go to the General Information tab in the developer portal, and scroll down to the `Linked Roles Verification Url` field. Paste the base URL to your Glitch app, add the `/linked-role` route, then save.
-
-
-
-For the Glitch project used in the screenshots, the verification URL would be `https://adjoining-crawling-yamamomo.glitch.me/linked-role`
-
-
-
-
-
-Finally, to generate a unique cookie secret, go back to Glitch, and click on the `Terminal` tab. Run the following commands:
-
-```
-$ node
-crypto.randomUUID()
-```
-
-Copy the randomly generated UUID, and paste it into your `.env` as `COOKIE_SECRET`. Your `.env` should look something like this:
-
-```
-DISCORD_CLIENT_ID:
-DISCORD_CLIENT_SECRET:
-DISCORD_TOKEN:
-DISCORD_REDIRECT_URI: https://.glitch.me/discord-oauth-callback
-COOKIE_SECRET:
-```
-
-## Registering your metadata schema
-
-As a one-time step, you must tell Discord which metadata fields you are going to allow admins to use for linked roles associated with your app.
-
-To configure connection metadata for your app, you'll call the [PUT /users/@me/applications/\/role-connection](/developers/docs/resources/application-role-connection-metadata#update-application-role-connection-metadata-records) method with [application connection role metadata](/developers/docs/resources/application-role-connection-metadata#application-role-connection-metadata-object). In the sample app, this is handled in [`src/register.js`](https://github.com/discord/linked-roles-sample/blob/main/src/register.js), and can be run via the command line.
-
-Go back to Glitch, click the **terminal** tab, and run the following command:
-
-```
-$ node src/register.js
-```
-
-
-
-## Trying it out
-
-Now that you've built your app, let's give it a try both from the server owner and the user's perspective.
-
-### Creating the linked role
-
-To try out the app, we'll create a linked role in a server where you have admin permissions. Open up the **Server Settings**, select **Roles**, and click on `Create Role`.
-
-Give the role a name, save it, then click on `Links`. Click the `Add requirement` button, and you should see your bot in the list of available Apps. Click on it, and you will see a setup screen where you can configure specific criteria for your role.
-
-
-
-### Acquiring the role
-
-To acquire your newly created role, click the server name in the upper left corner of the screen, and select `Linked Roles`. Click on your role, and it will present the opportunity to connect your account.
-
-
-
-When you connect your account, one of the scopes requested in the OAuth flow is `role_connections.write`, which is required for an app to update a user's role connection information.
-
-
-
-
-
-Click on the linked role criteria. This should lead to the Discord OAuth2 consent screen. Click `Authorize`, and then return to Discord.
-
-
-
-After returning to Discord, you should see your account granted the linked role.
-
-
-
-Finally, create a new private channel, and add the new linked role.
-
-## Tips & Tricks
-
-### Token storage
-
-This app largely relies on Discord's [OAuth2](/developers/docs/topics/oauth2) implementation to obtain access tokens. This model of user based authentication relies on storing refresh tokens, and using them to acquire access tokens. The example code in [`src/storage.js`](https://github.com/discord/linked-roles-sample/blob/main/src/storage.js) uses in-memory storage to manage these tokens, but for any production deployment a database with persistent storage should be used.
-
-### Advanced examples
-
-For a more complex example using the Fitbit API, see https://github.com/JustinBeckwith/fitbit-discord-bot/.
diff --git a/discord/developers/docs/tutorials/hosting-on-cloudflare-workers.md b/discord/developers/docs/tutorials/hosting-on-cloudflare-workers.md
deleted file mode 100644
index fb011a3ceb..0000000000
--- a/discord/developers/docs/tutorials/hosting-on-cloudflare-workers.md
+++ /dev/null
@@ -1,365 +0,0 @@
----
-sidebar_label: Hosting on Cloudflare Workers
----
-
-# Hosting a Reddit API Discord app on Cloudflare Workers
-
-When building Discord apps, your app can receive common events from the client as [webhooks](/developers/docs/resources/webhook) when users interact with your app through interactions like [application commands](/developers/docs/interactions/application-commands) or [message components](/developers/docs/components/reference).
-
-Discord will send these events to a pre-configured HTTPS endpoint (called an Interactions Endpoint URL in an app's configuration) as a JSON payload with details about the event.
-
-This tutorial walks through building a Discord app powered by [`r/aww`](https://www.reddit.com/r/aww) using JavaScript:
-
-
-
-All of the code for this app can be found **[on GitHub](https://github.com/discord/cloudflare-sample-app)**.
-
-### Features and technologies used
-
-- [Discord Interactions API](/developers/docs/interactions/receiving-and-responding) (specifically slash commands)
-- [Cloudflare Workers](https://workers.cloudflare.com/) for hosting
-- [Reddit API](https://www.reddit.com/dev/api/) to send messages back to the user
-
----
-
-## Creating an app on Discord
-
-To start, we'll create the app through the [Discord Developer Dashboard](https://discord.com/developers/applications):
-
-- Visit https://discord.com/developers/applications
-- Click `New Application`, and choose a name
-- Copy your **Public Key** and **Application ID**, and put them somewhere locally (we'll need these later)
-
-
-
-- Now click on the **Bot** tab on the left sidebar.
-- Grab the `token` for your bot, and store it somewhere safe (I like to put these tokens in a password manager like [1password](https://1password.com/) or [lastpass](https://www.lastpass.com/)).
-
-
-
-For security reasons, you can only view your bot token once. If you misplace your token, you'll have to generate a new one.
-
-
-
-## Adding bot permissions
-
-Now we'll configure the bot with [permissions](/developers/docs/topics/permissions) required to create and use slash commands, as well as send messages in channels.
-
-- Click on the `OAuth2` tab, and choose the `URL Generator`. Click the `bot` and `applications.commands` scopes.
-- Check the boxes next to `Send Messages` and `Use Slash Commands`, then copy the `Generated URL`.
-
-
-
-- Paste the URL into the browser and follow the OAuth flow, selecting the server where you'd like to develop and test your bot.
-
-## Creating your Cloudflare Worker
-
-Cloudflare Workers are a convenient way to host Discord apps due to the free tier, simple development model, and automatically managed environment (no VMs!).
-
-
-
-When using Cloudflare Workers, your app won't be able to access non-ephemeral CDN media. For example, trying to fetch an image like `https://cdn.discordapp.com/attachments/1234/56789/my_image.png` would result in a `403` error. Cloudflare Workers are still able to access ephemeral CDN media.
-
-
-
-- Visit the [Cloudflare Dashboard](https://dash.cloudflare.com/)
-- Click on the `Workers` tab, and create a new service using the same name as your Discord bot
-- Make sure to [install the Wrangler CLI](https://developers.cloudflare.com/workers/cli-wrangler/install-update/) and set it up.
-
-### Storing secrets
-
-The production service needs access to some of the information we saved earlier. To set those variables, run:
-
-```
-$ wrangler secret put DISCORD_TOKEN
-$ wrangler secret put DISCORD_PUBLIC_KEY
-$ wrangler secret put DISCORD_APPLICATION_ID
-```
-
-You'll also need the Guild ID for the server where your app is installed. This can be found in the URL when you visit any channel in that server.
-
-
-
-For example, if my URL was `https://discord.com/channels/123456/789101112`, the Guild ID is the first number—in this case **`123456`**.
-
-
-
-Once you know your Guild ID, set that variable as well:
-
-```
-$ wrangler secret put DISCORD_TEST_GUILD_ID
-```
-
-## Running locally
-
-
-
-This depends on the beta version of the `wrangler` package, which better supports ESM on Cloudflare Workers.
-
-
-
-Let's start by cloning the repository and installing dependencies. This requires at least v16 of [Node.js](https://nodejs.org/en/):
-
-```
-$ npm install
-```
-
-### Project structure
-
-A brief look at the cloned app's project structure:
-
-```
-├── .github/workflows/ci.yaml -> GitHub Action configuration
-├── src
-│ ├── commands.js -> JSON payloads for commands
-│ ├── reddit.js -> Interactions with the Reddit API
-│ ├── register.js -> Sets up commands with the Discord API
-│ ├── server.js -> Discord app logic and routing
-├── test
-| ├── test.js -> Tests for app
-├── wrangler.toml -> Configuration for Cloudflare Workers
-├── package.json
-├── README.md
-├── renovate.json -> Configuration for repo automation
-├── .eslintrc.json
-├── .prettierignore
-├── .prettierrc.json
-└── .gitignore
-```
-
-### Registering commands
-
-Before testing our app, we need to register our desired slash commands. For this app, we'll have a `/awwww` command, and a `/invite` command. The name and description for these are kept separate in `commands.js`:
-
-```js
-export const AWW_COMMAND = {
- name: 'awwww',
- description: 'Drop some cuteness on this channel.',
-};
-
-export const INVITE_COMMAND = {
- name: 'invite',
- description: 'Get an invite link to add the bot to your server',
-};
-```
-
-The code to register commands lives in `register.js`. Commands can be [registered globally](/developers/docs/interactions/application-commands#create-global-application-command), making them available for all servers with the app installed, or they can be [registered on a single server](/developers/docs/interactions/application-commands#create-guild-application-command).
-
-In this example - we'll just focus on global commands:
-
-```js
-import { AWW_COMMAND, INVITE_COMMAND } from './commands.js';
-import fetch from 'node-fetch';
-
-/**
- * This file is meant to be run from the command line, and is not used by the
- * application server. It's allowed to use node.js primitives, and only needs
- * to be run once.
- */
-
-const token = process.env.DISCORD_TOKEN;
-const applicationId = process.env.DISCORD_APPLICATION_ID;
-
-if (!token) {
- throw new Error('The DISCORD_TOKEN environment variable is required.');
-}
-if (!applicationId) {
- throw new Error(
- 'The DISCORD_APPLICATION_ID environment variable is required.'
- );
-}
-
-/**
- * Register all commands globally. This can take o(minutes), so wait until
- * you're sure these are the commands you want.
- */
-async function registerGlobalCommands() {
- const url = `https://discord.com/api/v10/applications/${applicationId}/commands`;
- await registerCommands(url);
-}
-
-async function registerCommands(url) {
- const response = await fetch(url, {
- headers: {
- 'Content-Type': 'application/json',
- Authorization: `Bot ${token}`,
- },
- method: 'PUT',
- body: JSON.stringify([AWW_COMMAND, INVITE_COMMAND]),
- });
-
- if (response.ok) {
- console.log('Registered all commands');
- } else {
- console.error('Error registering commands');
- const text = await response.text();
- console.error(text);
- }
- return response;
-}
-
-await registerGlobalCommands();
-```
-
-### Running the server
-
-This command needs to be run locally, once before getting started:
-
-```
-$ DISCORD_TOKEN=**** DISCORD_APPLICATION_ID=**** node src/register.js
-```
-
-We're finally ready to run this code locally! Let's start by running our local development server:
-
-```
-$ npm run dev
-```
-
-### Setting up ngrok
-
-When a user types a slash command, Discord will send an HTTP request to a public endpoint. During local development this can be a little challenging, so we're going to use [a tool called `ngrok`](https://ngrok.com/) to create an HTTP tunnel.
-
-```
-$ npm run ngrok
-```
-
-
-
-This is going to bounce requests off of an external endpoint, and forward them to your machine. Copy the HTTPS link provided by the tool. It should look something like `https://8098-24-22-245-250.ngrok.io`.
-
-Now head back to the Discord Developer Dashboard, and update the `Interactions Endpoint URL` for your app:
-
-
-
-This is the process we'll use for local testing and development. When you've published your app to Cloudflare, you will **want to update this field to use your Cloudflare Worker URL.**
-
-## Deployment
-
-This repository is set up to automatically deploy to Cloudflare Workers when new changes land on the `main` branch. To deploy manually, run `npm run publish`, which uses the `wrangler publish` command under the hood.
-
-Publishing via a GitHub Action requires obtaining an [API Token and your Account ID from Cloudflare](https://developers.cloudflare.com/workers/cli-wrangler/authentication/). These are stored [as secrets in the GitHub repository](https://docs.github.com/en/actions/security-guides/encrypted-secrets), making them available to GitHub Actions.
-
-The following configuration in `.github/workflows/ci.yaml` demonstrates how to tie it all together:
-
-```yaml
-release:
- if: github.ref == 'refs/heads/main'
- runs-on: ubuntu-latest
- needs: [test, lint]
- steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
- with:
- node-version: 16
- - run: npm install
- - run: npm run publish
- env:
- CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
- CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
-```
-
-## Code deep dive
-
-Most of the interesting code in this app lives in `src/server.js`. Cloudflare Workers require exposing a `fetch` function, which is called as the entry point for each request. This code will largely do two things for us: validate the request is valid and actually came from Discord, and hand the request over to a router to help give us a little more control over execution.
-
-```js
-export default {
- /**
- * Every request to a worker will start in the `fetch` method.
- * Verify the signature with the request, and dispatch to the router.
- * @param {*} request A Fetch Request object
- * @param {*} env A map of key/value pairs with env vars and secrets from the cloudflare env.
- * @returns
- */
- async fetch(request, env) {
- if (request.method === 'POST') {
- // Using the incoming headers, verify this request actually came from discord.
- const signature = request.headers.get('x-signature-ed25519');
- const timestamp = request.headers.get('x-signature-timestamp');
- const body = await request.clone().arrayBuffer();
- const isValidRequest = verifyKey(
- body,
- signature,
- timestamp,
- env.DISCORD_PUBLIC_KEY
- );
- if (!isValidRequest) {
- console.error('Invalid Request');
- return new Response('Bad request signature.', { status: 401 });
- }
- }
-
- // Dispatch the request to the appropriate route
- return router.handle(request, env);
- },
-};
-```
-
-All of the API calls from Discord in this example will be POSTed to `/`. From here, we will use the [`discord-interactions`](https://github.com/discord/discord-interactions-js) npm module to help us interpret the event, and to send results.
-
-```js
-/**
- * Main route for all requests sent from Discord. All incoming messages will
- * include a JSON payload described here:
- * https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object
- */
-router.post('/', async (request, env) => {
- const message = await request.json();
- console.log(message);
- if (message.type === InteractionType.PING) {
- // The `PING` message is used during the initial webhook handshake, and is
- // required to configure the webhook in the developer portal.
- console.log('Handling Ping request');
- return new JsonResponse({
- type: InteractionResponseType.PONG,
- });
- }
-
- if (message.type === InteractionType.APPLICATION_COMMAND) {
- // Most user commands will come as `APPLICATION_COMMAND`.
- switch (message.data.name.toLowerCase()) {
- case AWW_COMMAND.name.toLowerCase(): {
- console.log('handling cute request');
- const cuteUrl = await getCuteUrl();
- return new JsonResponse({
- type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
- data: {
- content: cuteUrl,
- },
- });
- }
- case INVITE_COMMAND.name.toLowerCase(): {
- const applicationId = env.DISCORD_APPLICATION_ID;
- const INVITE_URL = `https://discord.com/oauth2/authorize?client_id=${applicationId}&scope=applications.commands`;
- return new JsonResponse({
- type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
- data: {
- content: INVITE_URL,
- flags: InteractionResponseFlags.EPHEMERAL,
- },
- });
- }
- default:
- console.error('Unknown Command');
- return new JsonResponse({ error: 'Unknown Type' }, { status: 400 });
- }
- }
-
- console.error('Unknown Type');
- return new JsonResponse({ error: 'Unknown Type' }, { status: 400 });
-});
-```
-
-## Next steps
-
-
-
-In case you need to reference any of the code, you can find the repo [on GitHub](https://github.com/discord/cloudflare-sample-app)
-
-
-
-With your app built and deployed, you can start customizing it to be your own:
-
-- Use **[message components](/developers/docs/components/reference)** in your app to add more interactivity (like buttons and select menus).
-- Take a look at different **[public APIs](https://github.com/public-apis/public-apis)** on GitHub.
-- Join the **[Discord Developers server](https://discord.gg/discord-developers)** to ask questions about the API, attend events hosted by the Discord API team, and interact with other developers.
diff --git a/discord/developers/docs/tutorials/upgrading-to-application-commands.md b/discord/developers/docs/tutorials/upgrading-to-application-commands.md
deleted file mode 100644
index 01e26ed2a1..0000000000
--- a/discord/developers/docs/tutorials/upgrading-to-application-commands.md
+++ /dev/null
@@ -1,316 +0,0 @@
----
-sidebar_label: Upgrading to Application Commands
----
-
-# Upgrading Apps to Use Application Commands
-
-As [message content has become a privileged intent](https://support-dev.discord.com/hc/en-us/articles/4404772028055-Message-Content-Privileged-Intent-FAQ) for verified apps, [application commands](/developers/docs/interactions/application-commands) are the primary way Discord users interact with apps. The three types of commands (slash commands, user commands, and message commands) act as entry points into apps, and can be registered globally or for a subset of guilds.
-
-This guide is intended to provide developers with apps currently using message content with a resource to walk through implementing and designing commands. Throughout the guide, the terms "application commands" and "commands" are used interchangeably.
-
-
-
-
-If you are developing an app for the first time, the [commands documentation](/developers/docs/interactions/application-commands) may be a more helpful resource for you.
-
-
-Before diving in, it’s worth noting that with the message content changes, apps can still access message content in their DMs with users, as well as when messages are sent that directly `@mentions` their bot user (since there is clear user intent that the bot can read those messages).
-
-And for apps that use message content in ways that can’t be ported to commands, you should review the [message content intent review policy](https://support-dev.discord.com/hc/en-us/articles/5324827539479) to see if you’re eligible to apply for the privileged intent.
-
----
-
-## Types of Commands
-
-There are three types of application commands: slash commands, user commands, and message commands. When building your app, whether migrating or starting from scratch, consider which type of command(s) makes sense for a given feature of your app.
-
-### Slash Commands
-
-[Slash commands](/developers/docs/interactions/application-commands#slash-commands) are the most common type of command. They are accessed by typing a forward slash (`/`) followed by the command’s name, or by using the plus button (+) to the left of the message input.
-
-Slash commands can appear in channels and DMs, so they’re helpful when an action is tied to a channel, a server, or nothing at all.
-
-### User Commands
-
-[User commands](/developers/docs/interactions/application-commands#user-commands) are in the context menu for users, which is accessed by right-clicking or tapping on any user. They’re helpful when an action is tied to an individual user, like a moderation app adding a timeout to someone.
-
-
-Within the context menus for users and messages, the `Apps` submenu will only appear if an app in that server has installed a corresponding command (whether or not an individual user can use the installed command).
-
-
-### Message Commands
-
-[Message commands](/developers/docs/interactions/application-commands#message-commands) are in the context menu for messages, which is accessed by right-clicking on a message, or by clicking on the ellipses at the top-right of a message. They’re helpful when an action is tied to a message, like creating a reminder to reply to a message the following day.
-
-### After This Section
-- Start thinking about how different app features might map to the different types of application commands.
-
-## Registering Commands
-
-Commands can be registered via HTTP requests after an app is authorized with the `applications.commands` scope. The `applications.commands` scope is also automatically included when an app requests the `bot` scope.
-
-
-There is a section on [designing commands](/developers/docs/tutorials/upgrading-to-application-commands#designing-for-commands) below implementation details that may be helpful as you start mapping out different commands
-
-
-The API endpoint to register (or create) commands is different depending on its scope:
-
-- **[Global commands](/developers/docs/interactions/application-commands#making-a-global-command)** are available in all of the servers where your app is installed, and can be created using the [`/applications/{YOUR APP ID}/commands` endpoint](/developers/docs/interactions/application-commands#create-global-application-command). All of your app's global commands will automatically be added to the servers your app is installed in, regardless of whether they were registered before or after installation.
-- **[Guild commands](/developers/docs/interactions/application-commands#making-a-guild-command)** are only available in the servers you explicitly add them to via the API, making them useful for features available only to a subset of guilds. They can be created using the [`/applications/{YOUR APP ID}/guilds/{A GUILD ID}/commands` endpoint](/developers/docs/interactions/application-commands#create-guild-application-command).
-
-While most apps won’t need to register more than a handful of commands, apps can have up to 100 global slash commands and 100 guild slash commands with unique names. They can also have 5 global user commands and 5 global message commands. Different limitations apply for global and guild commands, which can be found [in the documentation](/developers/docs/interactions/application-commands#registering-a-command).
-
-### Using Options as Parameters
-
-Command options is an optional field (`options`) that can be defined when creating commands. When used, options will display for the user to fill out during invocation. You can also provide dynamic option suggestions using the `autocomplete` field. Read more about options [in the documentation](/developers/docs/interactions/application-commands#application-command-object-application-command-option-structure).
-
-
-
-### Using Subcommands to Group Actions
-
-[Subcommands and subcommand groups](/developers/docs/interactions/application-commands#subcommands-and-subcommand-groups) help organize commands that are related to a shared resource or action. Instead of several top-level commands (like `/add-resource` and `/delete-resource`), you can have one top-level command with several subcommands (like `/resource add` and `/resource delete`).
-
-Subcommands use the same `options` field as passing parameters, but with a type of `2`.
-
-### Restricting Command Use
-
-[Application command permissions](/developers/docs/interactions/application-commands#permissions) allow users and apps to restrict command usage in a server. When commands are restricted for a user, they won't appear for them in the client.
-
-If your app currently relies on permissioning, using command permissions can be a way to port them. It also cleans up the command picker UI for users, making it easier for them to find your app’s commands that are most relevant to them.
-
-### Example Payload
-
-Below is a sample payload to create a global slash command with an optional parameter:
-
-```json
-{
- "name": "rock",
- "type": 1,
- "description": "Sends a picture of a rock",
- "options": [
- {
- "name": "type",
- "description": "Type of rock",
- "type": 3,
- "required": True,
- "choices": [
- {
- "name": "Igneous",
- "value": "rock_igneous"
- },
- {
- "name": "Sedimentary",
- "value": "rock_sedimentary"
- },
- {
- "name": "Metamorphic",
- "value": "rock_metamorphic"
- }
- ]
- }
- ]
- }
-```
-
-#### Default Permissions
-
-When [creating](/developers/docs/interactions/application-commands#create-global-application-command) or [updating](/developers/docs/interactions/application-commands#edit-global-application-command) a command, you can use the `default_member_permissions` field to restrict the command to a set of bitwise permissions that reflect the default permission flags a user must be granted in order to use the command.
-
-In addition, the `dm_permission` flag can be used to control whether a global command is available in DMs (not available for guild commands).
-
-#### Updating Permissions
-
-Permissions for specific roles, users, and channels can be updated by your app if you have the `applications.commands.permissions.update` scope and a [Bearer token](/developers/docs/topics/oauth2) that’s authenticated by a user with the necessary user permissions. Details about updating a command’s permissions are [in the documentation](/developers/docs/interactions/application-commands#permissions).
-
-### After This Section
-
-- Update your app to use the `applications.commands` scope
-- Decide whether each of your commands should be scoped globally (available to all servers) or to a guild (available to specific servers)
-- Decide what permissions your commands may need to run
-- Create your app’s commands using HTTP endpoints
-
-## Handling Commands
-
-Commands use the [interactions model](/developers/docs/interactions/receiving-and-responding) through HTTP-based outgoing webhooks or the WebSocket-based [Interaction Create gateway event](/developers/docs/events/gateway-events#interaction-create). Regardless of the transit method used to arrive, your app will receive relevant information when a Discord user triggers one of your app’s interactions.
-
-
-If you continue using Gateway events, you’ll still receive message events but the payloads will have empty string or array data for message content-related fields like `content`, `embeds`, `attachments`, and `components` while `poll` will be omitted. You can read more in the [message content intent](/developers/docs/events/gateway#message-content-intent) section.
-
-
-For commands, this means that each time one of your commands is used, your app will receive information like the command name and the user who triggered it. More information about this information is below in the section on [parsing command payloads](/developers/docs/tutorials/upgrading-to-application-commands#parsing-command-payloads).
-
-### Adding an Interactions Endpoint URL
-
-
-This step is specific to receiving interactions over HTTP. If you prefer to use the [Gateway](/developers/docs/events/gateway), this step won't be applicable to your app.
-
-
-Before your app can receive interactions, you’ll need to set up an **Interaction Endpoint URL** in your app settings. This endpoint should be a public URL where Discord can send all interactions-related requests.
-
-However, before adding your URL to your app settings, your endpoint must be set up to handle two things:
-
-1. **Responding to `PING` events**: When you save a URL in your settings, Discord will send a `POST` request with `type: 1`. To acknowledge this request (and thus verify your endpoint), you should return a `200` response with a payload containing `type: 1`. More information can be found in the [Receiving an Interaction documentation](/developers/docs/interactions/receiving-and-responding#receiving-an-interaction).
-2. **Verifying request signatures**: To ensure that requests are coming from Discord, your endpoint must verify each request using the included headers, specifically `X-Signature-Ed25519` and `X-Signature-Timestamp`. If the signature fails validating, your app should return a `401` response. More information and example code can be found in the [Security and Authorization documentation](/developers/docs/interactions/overview#setting-up-an-endpoint-validating-security-request-headers).
-
-
-Many libraries on the [Community Resources page](/developers/docs/developer-tools/community-resources#interactions) simplify verification and interaction request handling by exporting reusable functions and/or handling it automatically.
-
-
-After your URL is set up to handle signature verification and `PING` requests, you can add your Interaction Endpoint URL by navigating to your app settings from the [developer portal](https://discord.com/developers/applications). On the **General Information** page, you’ll see a field for your **Interactions Endpoint URL**.
-
-
-
-After you paste your URL and click **Save Changes**, Discord will attempt to verify your endpoint.
-
-If all goes well, your endpoint will successfully save. And if not, you should double check that your app is running with a public endpoint, is verifying request signatures, and is properly responding to `PING` requests.
-
-### Parsing Command Payloads
-
-Once your app has a verified endpoint, you should start being able to receive command requests from Discord.
-
-As mentioned above, these include information relevant to handling the command like its name, the user who invoked it, and the guild and channel it was invoked from. It also includes additional details that could be relevant, like the [command options](/developers/docs/interactions/application-commands#application-command-object-application-command-option-structure) or [locale information](/developers/docs/interactions/application-commands#localization).
-
-Since slash commands (`CHAT_INPUT` commands) are run in the context of a channel, you’ll notice that their payloads don’t contain any information about specific messages. If your app needs the message content, you can use [message commands](/developers/docs/interactions/application-commands#message-commands) which *do* include the message content.
-
-
-In the getting started guide’s repository, there’s a code sample showing [how to create and handle commands using JavaScript](https://github.com/discord/discord-example-app/blob/main/examples/command.js).
-
-
-Below is an example payload your app would receive when a user invoked a global command with an option:
-
-```json
-{
- "type": 2,
- "token": "A_UNIQUE_TOKEN",
- "member": {
- "user": {
- "id": "A_USER_ID",
- "username": "A_USERNAME",
- "avatar": "GUILD_AVATAR_HASH",
- "discriminator": "1337",
- "public_flags": 131141
- },
- "roles": ["12345678"],
- "premium_since": null,
- "permissions": "2147483647",
- "pending": false,
- "nick": null,
- "mute": false,
- "joined_at": "2019-04-14T12:14:14.000000+00:00",
- "is_pending": false,
- "deaf": false
- },
- "id": "INTERACTION_ID",
- "application_id": "YOUR_APP_ID",
- "app_permissions": "442368",
- "guild_id": "A_GUILD_ID",
- "guild_locale": "en-US",
- "locale": "en-US",
- "data": {
- "options": [{
- "name": "Igneous",
- "value": "rock_igneous"
- }],
- "name": "rock",
- "id": "APPLICATION_COMMAND_ID"
- },
- "channel_id": "ASSOCIATED_CHANNEL_ID"
-}
-```
-
-To determine how your app should handle an incoming command-related interaction, you can look in the `data` object which contains all of the command-specific information (including any options a user selected). Details about the full interactions object your app receives can be found in the [Interactions documentation](/developers/docs/interactions/receiving-and-responding#interaction-object).
-
-### After This Section
-
-- Setup a public endpoint for your app that verifies request signatures and responds to `PING` events
-- Add your endpoint to your app settings under Interactions Endpoint URL
-- Modify your code (or write new code) to handle the different commands you registered earlier
-
-## Designing for Commands
-
-Adding commands to your app can add discoverability and interactivity for users. While porting your app’s features, it’s worth considering how your app will be seen and used inside of the client. This section includes a handful of areas to consider when designing your app’s commands, and what happens after they’re invoked.
-
-
-
-CLIs (Command Line Interfaces) can be a helpful analogy when designing Discord commands, their options and subcommands, and how it all fits together into one experience. A good resource for this can be the open source [Command Interface Guidelines](https://clig.dev/).
-
-
-
-### Choosing a Name
-
-When creating a command, keep the name short and relevant. The name of the command should give users an idea of the action they’re invoking. A description can be a bit more verbose, leaving room to be more explicit about the action and its result.
-
-And when your app has several commands (and perhaps [subcommands](/developers/docs/interactions/application-commands#subcommands-and-subcommand-groups)), it’s important to keep the naming scheme consistent.
-
-#### Examples
-
-- You should use a descriptive name like `/stats` rather than a vague name like `/get` for a command that displays stats to a user.
-- You should use a shorter name like `/poll` rather than a verbose name like `/create-new-poll` for a command that creates a new poll. If there are many actions to take related to `/poll`, it might be more intuitive to use a `create` subcommand.
-
-### Collecting User Input
-
-When commands need a bit of input from a user, you can use the `options` field. Command options can be thought of as parameters to your command. They can be one of many [types](/developers/docs/interactions/application-commands#application-command-object-application-command-option-type), like the standard string or number, or the more Discord-specific role, user, and channel.
-
-Options are great for short input, but if you need user input that’s longer than a couple of words, like a title or description, you can collect form-like input using [modals](/developers/docs/interactions/receiving-and-responding#interaction-response-object-modal) as a response to the command invocation.
-
-### Scoping a Command
-
-Commands can optionally be [scoped to specific guilds](/developers/docs/interactions/application-commands#create-guild-application-command), rather than available everywhere your app is installed. Guild commands can be useful when your app has functionality that may not be relevant to all servers like:
-
-- When a command is in development
-- When a specific command is opt-in or opt-out
-- When specific commands are behind a paywall
-
-### Responding to a Command
-
-Interactions (including commands) can have a hand-picked reply using one of the many available [interaction responses](/developers/docs/interactions/receiving-and-responding#responding-to-an-interaction).
-
-The specific response type should be picked based on the situation. Some commands may call for sending a message back to the channel where the command was invoked from, or perhaps just to the specific user who ran the command (for this, the [ephemeral message flag](/developers/docs/interactions/receiving-and-responding#interaction-response-object-messages) can be used). Other commands may necessitate descriptive input from the user, in which case responding with a follow-up modal with text inputs might make the most sense.
-
-Regardless of the response, it should be picked based on the specific interaction the user is taking.
-
-#### Example
-
-For a `/search` command that searches an external service, an app could respond with an ephemeral message rather than posting back into the channel where users may not have context or want messages cluttering the channel.
-
-Ephemeral messages can also contain message components, so when relevant, there could be a button to share the information in the ephemeral message to a channel.
-
-
-
-## Onboarding Users
-
-Once you’ve implemented slash commands (or really any feature for your app), it can be helpful to onboard existing and new users. While every app on Discord is unique, this section tries to generalize some good onboarding strategies, specifically to send updates to existing users.
-
-### Communicating App Updates to Users
-
-When you add new features or make major changes to your app, communicate what they are and how it specifically affects them. What do they need to do differently? What improves? What won’t they be able to do anymore?
-
-As to where to communicate the changes, you can start with any communication channels you own—a support server, blog, or social media account for example.
-
-You can also inform users about changes within the servers your app is installed in as long as it’s done in a non-intrusive way. If your app has a dedicated channel in posts, that would be a good place.
-
-
-
-Don’t DM all users in a server where your app is installed. It could get your app rate limited, but more importantly, it can be pretty intrusive and might lead to your app being uninstalled.
-
-
-
-#### Example
-
-The following is an example of an app update that may be sent to communicate the new way to access commands. Depending on the different features your app adopts (like options, subcommands, permissions, etc.), an update message or changelog entry will look very different.
-
-
-
-### Making Help Available
-
-Both new and existing users should always have ways for them to easily find usage instructions and support. Some of this help can come in the form of a support server or website, but you should also have instructions in the client.
-
-This can come in the form of a specific command that shows app usage, a message when someone `@mentions` your bot user, reactively when someone misuses one of your app’s commands, or ideally all of the above.
-
-## Further Resources
-
-Hopefully this guide was helpful in considering how to design and implement application commands. Below is a couple of follow-up resources you can use:
-
-- [Application command documentation](/developers/docs/interactions/application-commands)—I know it's linked a bunch in this guide, but there's a reason!
-- Help center article on [message content intent workarounds](https://support-dev.discord.com/hc/en-us/articles/6383579033751-Message-Content-Intent-Alternatives-Workarounds)
-- The [DDevs server](https://discord.gg/discord-developers) where you can find API updates, ask questions about developing apps, and connect with other developers