Skip to main content
This feature is currently available with limited access. To apply for full access to closed beta features, or to reach out to Discord directly to discuss your game, please fill out this form.

Overview

Linked Channels let players connect in-game lobbies with Discord text channels, enabling chat between your game and Discord servers. When linked:
  • In-game messages appear in the Discord channel
  • Discord messages appear in your game
  • Messages from your game show your game’s name and icon in Discord

Prerequisites

Before implementing Linked Channels, make sure you have:
To utilize this communication feature, you must enable Client::GetDefaultCommunicationScopes in your OAuth Scope configuration. See the OAuth Scopes Core Concepts Guide for more details.

Linked Channel Requirements

Channel Requirements

For a Discord channel to be linkable with your game lobby, it must meet these requirements:

Channel Type and Settings

RequirementDescription
Channel TypeMust be a Discord text channel in a server
NSFW StatusCannot be marked as NSFW
Link StatusCannot be currently linked to another lobby

Required Permissions

The user linking the channel must have these Discord permissions:
PermissionDescription
Manage ChannelsAbility to edit channel settings
View ChannelCan see and read the channel
Send MessagesCan post messages in the channel

Private Channels

Discord allows all channels the user can access in a server to be linked in game, even if that channel is private to other server members. This means a user could choose to link a private “admins chat” channel (assuming they are an admin) in the game if they wanted. It’s not possible for the game to know which users should have access to that channel. Every lobby member can view and reply to all messages sent in the linked channel.
If you are going to allow private channels to be linked in-game, you must make sure that users are aware that their private channel will be viewable by everyone in the lobby.
To help you identify which channels are public or private, we have added a isViewableAndWriteableByAllMembers boolean. You can use that boolean to prevent private channels from being linked or to know when to show a clear warning; it’s up to you!

User Requirements

Linking A Lobby

The lobby member must have the CanLinkLobby flag set to link a channel to a lobby. This flag is disabled by default and must be explicitly set using the Lobby API for users you want elevated permissions. We recommend only toggling this on for the equivalent of the administrator/owner of a lobby. This allows you, as the game developer, to say, “Only the admins of this guild are allowed to configure the linked channel.”

Unlinking a Lobby

To unlink a channel from a lobby, lobby members only require the CanLinkLobby flag to be set for them. They do not need to have any permissions on the Discord side.

Lobby Requirements

We recommend only using channel linking for persistent lobbies. Ephemeral lobbies such as match-chat are not good candidates for linking. Lobbies created on the client side with secrets are also not eligible for channel linking.

Creating a Linked Channel

Channel linking happens entirely in the game. The user is never kicked out of the game to go to Discord to set it up. So, at a high level, you will need to fetch the list of servers (also known as guilds) and channels the user can access, show them some UI to pick a channel, and then save that selection back to Discord.

Fetch Available Servers (Guilds) and Channels

We provide a few helper methods in the SDK to fetch the guilds and channels to populate the lists. Client::GetUserGuilds will fetch the user’s Discord servers from our API. A list of GuildMinimal structs, including the guild ID and name, is returned on success. Client::GetGuildChannels takes a guildId and fetches all the channels in a single guild that the user can access. On success, returns a list of GuildChannel objects, which are shown below:
struct GuildChannel {
    struct LinkedLobby {
        uint64_t applicationId;
        uint64_t lobbyId;
    };
    uint64_t id;
    std::string name;
    bool isLinkable;
    bool isViewableAndWriteableByAllMembers;
    std::optional<LinkedLobby> linkedLobby;
};
  • isLinkable indicates whether the user can link the given guild channel. This includes checking for channel validity (Is it a text channel? Is it marked safe for work? Is it already linked to another lobby?) and validating the user’s channel permissions. (Check the Edit Lobby/Channel Link endpoint docs for a full list of requirements)
  • isViewableAndWriteableByAllMembers indicates if the channel in Discord has restrictions on any members’ or roles’ ability to read or write to it (e.g. the channel may be considered private in some way). These read/write permissions are only enforced in the Discord client. A player who may not be able to view the channel in-Discord can read/write to it in-game as long as they are a lobby member. It is important to notify the player performing the link that the channel contents may become exposed to players in-game who do not have access to the channel in Discord.
Once the user has chosen a channel to link to, you can call Client::LinkChannelToLobby to set or change the channel a lobby is linked to. You can also use Client::UnlinkChannelFromLobby to remove the link. The conditions specified in Linked Channel Requirements must be met for the given lobby, channel, and user.

Try It Out

To test Linked Channels before building out a player interface, here are some steps you can follow to get things working in a prototype using the Discord API:
  1. Create a lobby using the Create Lobby endpoint.
  2. Enable the CanLinkLobby flag (1 << 0) on your lobby member by either sending a request to the /lobbies/<lobby_id>/members/<user_id> endpoint or by including the member data in the body of the Create Lobby request.
  3. Identify a Discord server text channel that your lobby_member has the specified permissions enabled for (again, read/write and manage channels) and grab the channel’s id.
  4. Send a request to the /lobbies/<lobby_id>/channel-linking endpoint described above with the channel id.
Success! Your lobby and channel should now be linked, and if you send a message in the lobby you should see it appear in the channel and vice versa.

Example Implementation

Step 1: Set Up Message Handling

// filepath: your_game/channel_linking.cpp
void HandleDiscordMessage(const std::string& message) {
    std::cout << "📱 Game received: " << message << "\n";
    // Check if message is from the lobby
    // Display in your game UI
}

void SetupMessageHandlers(std::shared_ptr<discordpp::Client> client) {
    client->SetMessageCreatedCallback([](uint64_t messageId) {
        discordpp::MessageHandle message = client->GetMessageHandle(messageId);
        HandleDiscordMessage(message);
    });
}

Step 2: Fetch Available Servers

void FetchDiscordServers(std::shared_ptr<discordpp::Client> client) {
    client->GetUserGuilds([](auto result, const auto& guilds) {
        if (!result.Successful()) {
            std::cout << "❌ Failed to fetch guilds\n";
            return;
        }

        for (const auto& guild : guilds) {
            std::cout << "📁 Guild: " << guild.name << "\n";
            // Store guild IDs for later use
            SaveGuildId(guild.id);
        }
    });
}

void FetchChannelsForGuild(
    std::shared_ptr<discordpp::Client> client,
    uint64_t guildId
) {
    client->GetGuildChannels(guildId, [](auto result, const auto& channels) {
        if (!result.Successful()) return;

        for (const auto& channel : channels) {
            if (channel.isLinkable) {
                std::cout << "  📝 Channel: " << channel.name;
                if (!channel.isViewableAndWriteableByAllMembers) {
                    std::cout << " (Private)";
                }
                std::cout << "\n";
            }
        }
    });
}
void ShowPrivateChannelWarning() {
    std::cout << "⚠️ Warning: This is a private channel.\n";
    std::cout << "All lobby members will be able to see messages.\n";
    std::cout << "Do you want to continue? (y/n)\n";
    
    char response;
    std::cin >> response;
    return (response == 'y' || response == 'Y');
}

void LinkChannelToLobby(
    std::shared_ptr<discordpp::Client> client,
    uint64_t lobbyId,
    uint64_t channelId,
    bool isPrivate
) {
    if (isPrivate && !ShowPrivateChannelWarning()) {
        std::cout << "❌ Channel linking cancelled\n";
        return;
    }

    client->LinkChannelToLobby(
        lobbyId,
        channelId,
        [](auto result) {
            if (result.Successful()) {
                std::cout << "✅ Channel linked successfully!\n";
            } else {
                std::cout << "❌ Failed to link channel\n";
            }
        }
    );
}

Step 4: Send and Receive Messages

void SendLobbyMessage(
    std::shared_ptr<discordpp::Client> client,
    uint64_t lobbyId,
    const std::string& message
) {
    client->SendLobbyMessage(lobbyId, message, [](auto result) {
        if (!result.Successful()) {
            std::cout << "❌ Failed to send message\n";
        }
    });
}

void UnlinkChannel(
    std::shared_ptr<discordpp::Client> client,
    uint64_t lobbyId
) {
    client->UnlinkChannelFromLobby(lobbyId, [](auto result) {
        if (result.Successful()) {
            std::cout << "✅ Channel unlinked\n";
        }
    });
}

Step 5: Putting It All Together

Here’s how you might use these functions together:
// filepath: your_game/main.cpp
int main() {
    auto client = std::make_shared<discordpp::Client>();
    
    // Set up handlers
    SetupMessageHandlers(client);
    
    // When user wants to link a channel:
    FetchDiscordServers(client);
    
    // After user selects a guild:
    FetchChannelsForGuild(client, selectedGuildId);
    
    // After user selects a channel:
    LinkChannelToLobby(
        client,
        currentLobbyId,
        selectedChannelId,
        isPrivateChannel
    );
    
    // When sending a message:
    SendLobbyMessage(client, currentLobbyId, "Hello from the game!");
    
    // When done with the channel:
    UnlinkChannel(client, currentLobbyId);
    
    return 0;
}

Joining Discord Servers via Linked Lobbies

Once a lobby is linked to a Discord channel, players can join the associated Discord server directly from your game. This feature simplifies the process of getting players into your Discord community by generating invites on-demand, eliminating the need to manually share invite links. The Client::JoinLinkedLobbyGuild function generates a one-time-use invite for the current user and on supported platforms, automatically navigates them to Discord to accept it. For example, an in-game player flow could look like:
  1. A Discord server admin links a channel to your game’s lobby
  2. Players in the lobby see an option to “Join Discord Server” in your game
  3. When clicked, the SDK generates a unique invite and opens Discord
  4. The player accepts the invite and becomes a Discord server member
Only players with linked Discord accounts can join the server. If a player is using a provisional account, you should prompt them to link their Discord account first.
const uint64_t lobbyId = 1234567890;

// Invite the user to join the Discord guild associated with the linked lobby
client->JoinLinkedLobbyGuild(
    lobbyId,
    // This is triggered when the user is using a provisional account, since
    // the user needs a real Discord account to join the Discord server, so you don't need
    // to implement a provisional user check on implementation.
    [] {
        // Show a message in your UI explaining that they need to link their Discord account
        // and/or step them through the process
        std::cout << "📝 User needs to link their Discord account\n";
    },
    // Called after the invite generation attempt completes, providing either a
    // successful result with the invite URL or an error if the operation failed.
    [](const discordpp::ClientResult &result, const std::string& inviteUrl) {
        if(result.Successful()) {
            std::cout << "✅ Discord invite generated successfully!\n";

            // On console platforms, you'll need to display the invite URL
            // for users to manually navigate to
            #ifdef CONSOLE_PLATFORM
            std::cout << "Join the Discord server at: " << inviteUrl << "\n";
            // Display this URL in your game's UI for the player to use
            #endif
        } else {
            std::cerr << "❌ Failed to generate Discord invite\n";
        }
    }
);

Platform Considerations

  • Desktop: The SDK automatically opens the Discord client or web browser with the invite
  • Console: Since console platforms cannot navigate to Discord directly, you should display the invite URL in your game’s UI so players can use it on another device
Discord server admins cannot restrict who can join the server via this method. Any player in a linked lobby can generate an invitation to the server, regardless of their lobby permissions.
Make sure to make your players aware to only link channels in servers you trust your players to join, and/or provide in-game options to disable this feature for certain lobbies.

Next Steps

Need help? Join the Discord Developers Server and share questions in the #social-sdk-dev-help channel for support from the community. If you encounter a bug while working with the Social SDK, please report it here: https://dis.gd/social-sdk-bug-report

Change Log

DateChanges
June 30, 2025Add communications scope warning
March 17, 2025initial release