OAuth2
OAuth2 enables application developers to build applications that utilize authentication and data from the Discord API. Within Discord, there are multiple types of OAuth2 authentication. Supported grants include the authorization code grant, implicit grant, device grant, client credentials, and some modified special-for-Discord flows for bots and webhooks.
Shared Resources
The first step in implementing OAuth2 is registering a developer application and retrieving your client ID and client secret.
Most people who will be implementing OAuth2 will want to find and utilize a library in the language of their choice. For those implementing OAuth2 from scratch, please see RFC 6749 for details.
After you create your application with Discord, make sure that you have your client_id and client_secret handy. The next step is to figure out which OAuth2 flow is right for your purposes.
OAuth2 URLs
| URL | Description |
|---|---|
| https://discord.com/oauth2/authorize | Authorization URL |
| https://discord.com/activate | Device Code Authorization URL |
| https://discord.com/api/v10/oauth2/token | Token URL |
| https://discord.com/api/v10/oauth2/token/revoke | Token Revocation URL |
| https://discord.com/api/v10/oauth2/keys | JWKS URI |
| https://discord.com/api/v10/oauth2/userinfo | UserInfo URL |
OAuth2 Scopes
These are all the OAuth2 scopes that Discord supports. Some scopes require approval from Discord to use. Requesting them from a user without approval from Discord will lead to unexpected error behavior in the OAuth2 flow.
| Value | Description | Public |
|---|---|---|
| account.global_name.update | Allows updating the user's global name | No |
| activities.invites.write | Allows sending activity invites | No |
| activities.read | Allows retrieving user presence and activity data | No |
| activities.write | Allows updating user presence and creating headless sessions | No |
| applications.builds.read | Allows reading branch and build data for the user's applications | Yes |
| applications.builds.upload | Allows uploading builds to the user's applications | No |
| applications.commands 1 | Allows using commands in a guild/user context | Yes |
| applications.commands.permissions.update | Allows updating the application's own command permissions in guilds the user has permissions in | Yes |
| applications.commands.update 2 | Allows your app to update its own commands | Yes |
| applications.entitlements | Allows managing entitlements for the user's applications | Yes |
| applications.store.update | Allows managing store data (SKUs, store listings, achievements, etc.) for the user's applications | Yes |
| application_identities.write | Allows managing application identities | No |
| bot | Adds the application's bot to a user-selected guild | Yes |
| connections | Allows retrieving a user's connected accounts, both public and private | Yes |
| dm_channels.read | Allows reading information about the user's DMs and group DMs | No |
| dm_channels.messages.read | Allows reading messages from the user's DMs and group DMs | No |
| dm_channels.messages.write | Allows sending messages to the user's DMs | No |
| email 3 | Allows retrieving a user's email address | Yes |
| gateway.connect 3 | Allows connecting to the gateway on behalf of the user | No |
| gdm.join | Allows adding users to managed group DMs | Yes |
| guilds | Allows retrieving the user's guilds | Yes |
| guilds.channels.read | Allows reading the channels in a user's guilds | No |
| guilds.join | Allows joining users to a guild | Yes |
| guilds.members.read | Allows retrieving a user's member information in a guild | Yes |
| identify | Allows retrieving the current user | Yes |
| lobbies.write | Allows managing lobbies | No |
| messages.read | When using RPC, allows reading messages from all client channels (otherwise restricted to application-managed group DMs) | Yes |
| openid | Allows retrieving basic user information and includes an ID token in the token exchange | Yes |
| payment_sources.country_code | Allows retrieving the user's country code | No |
| presences.read | Allows retrieving user presence | No |
| presences.write | Allows updating user presence | No |
| relationships.read 9 | Allows retrieving a user's relationships | Yes |
| relationships.write | Allows managing a user's relationships | No |
| role_connections.write 4 | Allows updating a user's connection and application-specific metadata | Yes |
| rpc 5 6 | When using RPC, allows controlling the local Discord client; also encompasses all of the below RPC scopes in the majority of scenarios | No |
| rpc.activities.write 6 | When using RPC, allows updating a user's activity | Yes |
| rpc.notifications.read 6 | When using RPC, allows you to receive notifications pushed out to the user | Yes |
| rpc.screenshare.read 6 | When using RPC, allows reading a user's screenshare status | Yes |
| rpc.screenshare.write 6 | When using RPC, allows updating a user's screenshare settings | Yes |
| rpc.video.read 6 | When using RPC, allows reading a user's video status | Yes |
| rpc.video.write 6 | When using RPC, allows updating a user's video settings | Yes |
| rpc.voice.read 6 | When using RPC, allows reading a user's voice settings and listening for voice events | Yes |
| rpc.voice.write 6 | When using RPC, allows updating a user's voice settings | Yes |
| voice 3 7 | Allows connecting to voice on the user's behalf and seeing all voice members in a guild | No |
| webhook.incoming 8 | Creates an application-owned webhook in a user-selected channel and returns it in the token exchange | Yes |
1 In a user install context, this scope also allows the application to send DMs to the user.
2 Only available through the client credentials grant flow.
3 Depends on the identify scope being authorized as well.
4 Only available through the authorization code grant flow and requires that the PUBLIC_OAUTH2_CLIENT application flag is not set.
5 Unless the application is approved for general RPC access, the rpc scope is allowed for the application owner and whitelisted users only and requires that the EMBEDDED application flag is not set.
6 Access to RPC for web applications requires approval from Discord.
7 Also includes gateway.connect privileges.
8 Only available through the authorization code grant flow.
9 Requires the SOCIAL_LAYER_INTEGRATION_LIMITED or SOCIAL_LAYER_INTEGRATION application flag.
Umbrella OAuth2 Scopes
The following scopes are considered "umbrella" scopes, meaning that they are used to request access to multiple scopes at once. These are currently only used by the social layer integration.
| Value | Description |
|---|---|
| sdk.social_layer_presence | Includes the scopes activities.invites.write, activities.read, activities.write, application_identities.write, gateway.connect, identify, relationships.read, and relationships.write |
| sdk.social_layer | Includes everything in sdk.social_layer_presence, plus dm_channels.read, dm_channels.messages.read, dm_channels.messages.write, guilds, guilds.channels.read, and lobbies.write |
Authorization URL Structure
| Field | Type | Description |
|---|---|---|
| client_id | snowflake | The ID of the application |
| response_type? 1 | string | The type of response to return |
| scope? 2 | string | A space-delimited list of scopes to request; may be omitted if the application has a populated integration_types_config |
| redirect_uri? 3 | string | The URL to redirect to after authorization; must match one of the registered redirect URIs for the application |
| prompt? | string | The prompt behavior to use for the authorization flow (default consent) |
| state? | string | A unique string to bind the user's request to their authenticated state |
| nonce? | string | A unique string to bind the user's request to their authenticated state; only applicable for authorization code grants with the openid scope |
| code_challenge? | string | A code challenge for the PKCE extension to the authorization code grant; must be used with code_challenge_method |
| code_challenge_method? | string | The method used to generate the code challenge (must be S256); only applicable for the PKCE extension to the authorization code grant |
| integration_type? | integer | The installation context for the authorization; only applicable when scope contains applications.commands (default GUILD_INSTALL) |
| permissions? | integer | The permissions you're requesting; only applicable when scope contains bot |
| guild_id? | snowflake | The ID of a guild to pre-fill the dropdown picker with; only applicable when scope contains bot, applications.commands, or webhook.incoming and integration_type is GUILD_INSTALL |
| channel_id? | snowflake | The ID of a channel to pre-fill the dropdown picker with; only applicable when scope contains webhook.incoming |
| disable_guild_select? | boolean 4 | Disallows the user from changing the guild dropdown; only applicable when scope contains bot or applications.commands, or webhook.incoming and integration_type is GUILD_INSTALL (default false) |
1 Required unless the basic bot authorization flow is used.
2 If the bot scope is selected, the applications.commands scope is automatically added to the authorization by official clients.
3 If a response_type is specified and no redirect_uri is specified, the user will be redirected to the first registered redirect URI for the application.
4 Only accepts true or false.
Response Type
| Value | Description |
|---|---|
| code | Authorization code grant flow |
| token | Implicit grant flow |
Prompt Behavior
| Value | Description |
|---|---|
| none | Skips the authorization screen and immediately redirects the user; requires previous authorization with the requested scopes |
| consent | Prompts the user to re-approve their authorization |
State and Security
Before we dive into the semantics of the different OAuth2 grants, we should stop and discuss security, specifically the use of the state parameter.
Cross Site Request Forgery, or CSRF, and Clickjacking are security vulnerabilities that must be addressed by individuals implementing OAuth.
This is typically accomplished using the state parameter. state is sent in the authorization request and returned back in the response and should be a value that binds the user's request to their authenticated state.
For example, state could be a hash of the user's session cookie, or some other nonce that can be linked to the user's session.
When a user begins an authorization flow on the client, a state is generated that is unique to that user's request. This value is stored somewhere only accessible to the client and the user, i.e. protected by the same-origin policy.
When the user is redirected, the state parameter is returned. The client validates the request by checking that the state returned matches the stored value. If they match, it is a valid authorization request.
If they do not match, it's possible that someone intercepted the request or otherwise falsely authorized themselves to another user's resources, and the request should be denied.
For OpenID Connect, the nonce parameter may be used in a similar way instead. Upon receiving the ID token, the client should validate that the nonce claim in the ID token matches the nonce sent in the authorization request.
While Discord does not require the use of the state parameter, we highly recommend that you implement it for the security of your own applications and data.
Authorization Code Grant
The authorization code grant is what most developers will recognize as "standard OAuth2" and involves retrieving an access code and exchanging it for a user's access token. It allows the authorization server to act as an intermediary between the client and the resource owner, so the resource owner's credentials are never shared directly with the client.
Example Authorization URL
When someone navigates to this URL, they will be prompted to authorize your application for the requested scopes.
On acceptance, they will be redirected to your redirect_uri, which will contain an additional query-string parameter, code. state will also be returned if previously sent, and should be validated at this point.
prompt controls how the authorization flow handles existing authorizations. If a user has previously authorized your application with the requested scopes and prompt is set to consent, it will request them to reapprove their authorization.
If set to none, it will skip the authorization screen and redirect them back to your redirect URI without requesting their authorization. For passthrough scopes, like bot and webhook.incoming, authorization is always required.
The integration_type parameter specifies the installation context for the authorization. The installation context determines where the application will be installed, and is only relevant when scope contains applications.commands.
When set to GUILD_INSTALL, the application will be authorized for installation to a guild. When set to USER_INSTALL, the application will be authorized for installation to a user. The application must be configured to support the provided integration_type.
Example Redirect URL
code is now exchanged for the user's access token by making a request to the token URL as follows:
Example Access Token Exchange
In response, you will receive an access token response:
Example Access Token
{"token_type": "Bearer","access_token": "ODkxNDM2MjMzOTAzOTY0MTYx.6qrZcUqja7812RVdnEKjpzOL4CvHBFG","scope": "identify","expires_in": 604800,"refresh_token": "D43f5y0ahjqew82jZ4NViEr2YafMKhue"}
Having the user's access token allows your application to make certain requests to the API on their behalf, restricted to whatever scopes were requested.
Refresh Token Grant
expires_in is how long, in seconds, until the returned access token expires, allowing you to anticipate the expiration and refresh the token. To refresh, make another request to the token URL with the following parameters:
Example Refresh Token Exchange
Boom; fresh access token response!
Implicit Grant
The implicit OAuth2 grant is a simplified flow optimized for in-browser clients. Instead of issuing the client an authorization code to be exchanged for an access token, the client is directly issued an access token. The URL is formatted as follows:
Example Authorization URL
On redirect, your redirect URI will contain additional URI fragments representing a serialiazed access token response: access_token, token_type, expires_in, scope, and state (if specified).
These are not query string parameters. Be mindful of the "#" character:
Example Redirect URL
There are tradeoffs in using the implicit grant flow. It is both quicker and easier to implement, but rather than exchanging a code and getting a token returned in a secure HTTP body, the access token is returned in the URI fragment, which makes it possibly exposed to unauthorized parties. You also are not returned a refresh token, so the user must explicitly reauthorize once their token expires.
Client Credentials Grant
The client credential flow is a quick and easy way for bot developers to get their own bearer tokens for testing purposes. By making a request to the token URL with a grant type of client_credentials,
you will be returned an access token for the bot owner. Therefore, always be super-extra-very-we-are-not-kidding-like-really-be-secure-make-sure-your-info-is-not-in-your-source-code careful with your client_id and client_secret. We don't take kindly to imposters around these parts.
You can specify scopes with the scope parameter, which is a list of OAuth2 scopes separated by spaces:
Example Client Credentials Request
In return, you will receive an access token (without a refresh token):
Example Access Token
{"token_type": "Bearer","access_token": "6qrZcUqja7812RVdnEKjpzOL4CvHBFG","scope": "identify connections","expires_in": 604800}
Note that team-owned applications are limited to the scopes applications.builds.read, applications.builds.upload, applications.commands.update, applications.entitlements, applications.store.update, and identify.
This is because these applications are owned by a pseudo-user that is not meant to be operated like a normal user account.
Device Code Grant
The device code grant is a flow that allows users to authenticate on devices that do not have a web browser or are otherwise unable to complete the OAuth2 flow in a traditional way.
To use the device code grant, you first need to make a request to the device code authorize URL to retrieve a device code and user code:
Example Device Code Request
In return, you will receive a response containing the necessary information to start the authorization process:
Example Device Code Response
{"device_code": "PZVqIuLlME19uotfsUATN65Ytgbejbhj7Eob8qzali","user_code": "ZAW6C586","verification_uri": "https://discord.com/activate","verification_uri_complete": "https://discord.com/activate?user_code=ZAW6C586","expires_in": 300,"interval": 5}
You should display the user_code and verification_uri to the user, or embed the verification_uri_complete link in a QR code for them to scan.
While you are prompting the user, you should also start polling the token URL to check if the user has completed the authorization process every interval seconds or until the expires_in time has passed:
Example Device Code Exchange
If the user has completed the authorization process, you will receive an access token response as usual.
PKCE
Discord supports the Proof Key for Code Exchange (PKCE) extension to the OAuth2 authorization code flow.
PKCE allows users to authenticate with your application without sharing your client secret. This enables user-facing applications such as browser extensions or mobile apps to manage authentication securely. The flow runs entirely between the user and Discord, allowing users to refresh their own bearer tokens without needing your application's client secret.
If you want your clients to be able to refresh their own tokens automatically, you will need to enable the PUBLIC_OAUTH2_CLIENT application flag.
When using PKCE, your application can also utilize custom schemes in redirect_uris.
Code Verifier
Firstly, the client needs to create a code verifier, code_verifier:
- The verifier must be a string of 43 - 128 characters.
- The characters must be alphanumeric (
A-Z,a-z,0-9) and hyphens-, periods., underscores_, and tildes~. - The code verifier must also be randomly generated for each authorization request.
The PKCE specification recommends that you generate a 32 byte random string and base64 URL encode it without padding, resulting in a 43-byte string.
Code Challenge
Next, the client needs to create a code challenge, code_challenge, which is the base64 URL-encoded SHA256 hash of the code_verifier, without padding.
SHA256 is the only supported hashing algorithm for PKCE in Discord's OAuth2 implementation.
The client then constructs the authorization URL with the code_challenge and code_challenge_method parameters:
Example Authorization URL
If successful, Discord will send you to the redirect URL with the usual authorization code.
The redirect URL can safely be forwarded to the client, as the code_challenge is not sensitive information. However, it is also acceptable to keep the credentials on the server instead.
When exchanging the authorization code for an access token, the client must include the code_verifier in the request. Note that to omit the client_secret field as shown below, you must have the PUBLIC_OAUTH2_CLIENT application flag set.
Example Access Token Exchange
This will give you an access token response as usual.
You can now refresh the token on the client, omitting the client_secret field depending on the PUBLIC_OAUTH2_CLIENT application flag.
Bots
So, what are bot accounts?
Bot vs User Accounts
Discord's API provides a separate type of user account dedicated to automation, called a bot account. Bot accounts can be created through the applications API and do not have an email and password. Unlike the normal OAuth2 flow, bot accounts have full access to all API routes without using bearer tokens, and can connect to the Real Time Gateway. Automating normal user accounts (generally called "self-bots") outside of the OAuth2/bot API is forbidden, and can result in an account termination if found. Don't get found :)
Bot accounts have a few differences in comparison to normal user accounts, namely:
- Bots are added to guilds through the OAuth2 API, and cannot accept normal invites.
- Bots cannot have friends, nor be added to or join Group DMs.
- Verified bots do not have a maximum number of Guilds.
- Bots have an entirely separate set of Rate Limits.
Bot Authorization Flow
Bot authorization is a special server-less and callback-less OAuth2 flow that makes it easy for users to add bots to guilds. The URL you create looks similar to what we use for full stack implementation:
Example Authorization URL
In the case of bots, the scope parameter should be set to bot. There's also a new parameter, permissions, which is an integer corresponding to the permission calculations for the bot.
You'll also notice the absence of response_type and redirect_uri. Bot authorization does not require these parameters because there is no need to retrieve the user's access token.
When the user navigates to this page, they'll be prompted to add the bot to a guild in which they have proper permissions. On acceptance, the bot will be added. Super easy!
If you happen to already know the ID of the guild the user will add your bot to, you can provide this ID in the URL as a guild_id=GUILD_ID parameter.
When the authorization page loads, that guild will be preselected in the dialog if that user has permissions to add the bot to that guild. You can use this in conjunction with the parameter disable_guild_select=true to disallow the user from picking a different guild.
If your bot is super specific to your private clubhouse, or you just don't like sharing, you can make sure integration_public is disabled on your application. If unchecked, only you can add the bot to guilds.
If marked as public, anyone with your bot's ID can add it to guilds in which they have proper permissions.
Advanced Bot Authorization
Devs can extend the bot authorization functionality. You can request additional scopes outside of bot, which will prompt a continuation into a complete authorization code grant flow and add the ability to request the user's access token.
If you request any scopes outside of bot or applications.commands, response_type is again mandatory.
When receiving the access code on redirect, there will be additional query-string parameters of guild_id and permissions.
These parameters should only be used as hints, as they are easily faked by malicious users. To be sure of the relationship between your bot and the guild, consider enabling integration_require_code_grant on your application.
Enabling it requires anyone adding your bot to a guild to go through a full OAuth2 authorization code grant flow, meaning the integration will not be created until your backend exchanges the code for a token.
When you retrieve the user's access token, you'll also receive information about the guild to which your bot was added through an additional guild object in the response.
Multi-Factor Authentication Requirement
For bots with elevated permissions (permissions with a * next to them), we enforce multi-factor authentication on the owner's account when added to guilds that have guild-wide MFA enabled.
Webhooks
Discord's webhook flow is a specialized version of an authorization code implementation. In this case, the scope query-string parameter needs to include webhook.incoming:
Example Authorization URL
When the user navigates to this URL, they will be prompted to select a channel in which to allow the webhook. When the webhook is executed, it will post its message into this channel.
On acceptance, the user will be redirected to your redirect_uri. The URL will contain the code query-string parameter which should be exchanged for an access token as usual.
In return, you will receive a slightly modified token response, with an additional webhook object:
Example Access Token
{"token_type": "Bearer","access_token": "GNaVzEtATqdh173tNHEXY9ZYAuhiYxvy","scope": "webhook.incoming","expires_in": 604800,"refresh_token": "PvPL7ELyMDc1836457XCDh1Y8jPbRm","webhook": {"type": 1,"id": "347114750880120863","name": "Application Name Here","avatar": "cc7e0aa58a4224a281fbb8217b808a72","channel_id": "345626669224982402","guild_id": "290926792226357250","application_id": "310954232226357250","token": "kKDdjXa1g9tKNs0-_yOwLyALC9gydEWP6gr9sHabuK1vuofjhQDDnlOclJeRIvYK-pj_","url": "https://discord.com/api/webhooks/347114750880120863/kKDdjXa1g9tKNs0-_yOwLyALC9gydEWP6gr9sHabuK1vuofjhQDDnlOclJeRIvYK-pj_"}}
From this object, you should store the webhook.id and webhook.token. See the execute webhook documentation for how to send messages with the webhook.
Any user that wishes to add your webhook to their channel will need to go through the full OAuth2 flow, and a new webhook is created each time. If you wish to send a message to all your webhooks,
you'll need to iterate over each stored id:token combination and make POST requests to each one. Be mindful of our Rate Limits!
OAuth2 Access Token Object
Access Token Structure
| Field | Type | Description |
|---|---|---|
| token_type | string | The type of token, always Bearer |
| access_token | string | The access token |
| id_token? 1 | string | The ID token |
| scope | string | The scopes the user has authorized, separated by space |
| expires_in | integer | Duration (in seconds) after which the token expires |
| refresh_token? | string | The refresh token, if applicable |
| guild? | guild object | The guild to which the bot was added, if applicable |
| webhook? | webhook object | The webhook created, if applicable |
1 Only returned from the Get Provisional Account Token endpoint and when using the authorization code grant with the openid scope.
OAuth2 Authorization Object
OAuth2 Authorization Structure
| Field | Type | Description |
|---|---|---|
| id | snowflake | The ID of the authorization |
| scopes | array[string] | The scopes the user has authorized the application for |
| application | partial application object | The authorized application |
| disclosures? | array[integer] | The application disclosures that have been acknowledged by the user |
Endpoints
Get Current Authorization Information
GET/oauth2/@meReturns info about the current authorization.
Response Body
| Field | Type | Description |
|---|---|---|
| application | partial application object | The current application |
| scopes | array[string] | The scopes the user has authorized the application for |
| expires | ISO8601 timestamp | When the access token expires |
| user? | partial user object | The user who has authorized, if the user has authorized with the identify scope |
Get OpenID Connect Keys
GET/oauth2/keysReturns the JSON Web Key Set used to verify OpenID Connect ID tokens issued by Discord. This endpoint is compliant with the OpenID Connect specification.
Get OpenID User Information
GET/oauth2/userinfoReturns OpenID user information for the current authorization. This endpoint is compliant with the OpenID Connect specification.
Response Body
| Field | Type | Description |
|---|---|---|
| sub | string | The ID of the user |
| email 1 | ?string | The user's email address |
| email_verified 1 | boolean | Whether the email on this account has been verified |
| preferred_username 2 | string | The user's username |
| nickname 2 | ?string | The user's display name |
| picture 2 | string | The user's avatar URL |
| locale 2 | string | The user's locale |
1 Requires the email scope.
2 Requires the identify scope.
Example Response
{"sub": "852892297661906993","email": "dolfies@amazing.email","email_verified": true,"preferred_username": "dolfies","nickname": "Dolfies","picture": "https://cdn.discordapp.com/avatars/852892297661906993/c78ef8fb1db15a3d5f1b4c057856c5c9.png","locale": "en-US"}
Get OAuth2 Device Code
POST/oauth2/device/authorizeRetrieves a device code and user code for the device code grant flow.
Form Params
| Field | Type | Description |
|---|---|---|
| client_id? 1 | snowflake | The ID of the application |
| client_secret? 1 2 | string | The client secret of the application |
| scope? | string | A space-delimited list of scopes to request |
1 You can also pass your client_id and client_secret as basic authentication with client_id as the username and client_secret as the password.
2 Not required if the application has the PUBLIC_OAUTH2_CLIENT application flag.
Response Body
| Field | Type | Description |
|---|---|---|
| device_code | string | The device code to use for the device code grant |
| user_code | string | The user code to display to the user for authorization |
| verification_uri | string | The URL to display to the user for authorization |
| verification_uri_complete | string | The complete URL to redirect the user to for authorization, including the user code |
| expires_in | integer | The duration (in seconds) after which the device code expires |
| interval | integer | The interval (in seconds) at which to poll the token endpoint for authorization status |
Get OAuth2 Device Flow
POST/oauth2/device/verifyReturns information about the OAuth2 device code grant flow.
JSON Params
| Field | Type | Description |
|---|---|---|
| user_code | string | The device code |
Response Body
| Field | Type | Description |
|---|---|---|
| scopes | array[string] | The scopes the user is authorizing the application for |
| client_id | snowflake | The ID of the application |
| two_way_link_code | ?string | The code to use for two-way linking |
| type | string | The status of the OAuth2 device flow |
OAuth2 Device Flow Status
| Value | Description |
|---|---|
| pending | The device flow is pending |
| granted | The device flow is completed and an access token was granted |
| denied | The device flow is completed but no access token was granted |
Finish OAuth2 Device Flow
POST/oauth2/device/finishFinishes the OAuth2 device code grant flow. Returns a 204 empty response on success.
JSON Params
| Field | Type | Description |
|---|---|---|
| user_code | string | The device code |
| result | string | The result of the flow (only granted and denied are allowed) |
Get OAuth2 Token
POST/oauth2/tokenRetrieves an OAuth2 access token for the given application credentials. Implements a number of different grants. Returns an oauth2 access token object on success.
Form Params
| Field | Type | Description |
|---|---|---|
| grant_type | string | The type of grant to use |
| client_id? 1 | snowflake | The ID of the application |
| client_secret? 1 2 | string | The client secret of the application |
| code? | string | The authorization code to exchange for a token |
| code_verifier? | string | The code verifier for the PKCE extension to the authorization code grant |
| redirect_uri? | string | The URL to redirect to after authorization; must match one of the registered redirect URIs for the application; only applicable for authorization_code grants |
| refresh_token? | string | The refresh token to exchange for a new access token |
| device_code? | string | The device code to exchange for an access token |
| scope? | string | A space-delimited list of scopes to request; only applicable for client_credentials grants |
| external_auth_type? 3 | string | The type of the external authentication provider |
| external_auth_token? 3 | string | The external authentication token |
1 You can also pass your client_id and client_secret as basic authentication with client_id as the username and client_secret as the password.
2 Required if the application does not have the PUBLIC_OAUTH2_CLIENT application flag, the grant_type is client_credentials, or the grant_type is authorization_code and code_verifier is not provided.
3 Providing these fields will merge the associated provisional account with the user account that is being authenticated. See the User Merge Operation Completed Gateway event for more information.
OAuth2 Grant Type
| Value | Description |
|---|---|
| authorization_code | Authorization code grant flow |
| refresh_token | Refresh token grant flow |
| client_credentials | Client credentials grant flow |
| urn:ietf:params:oauth:grant-type:device_code | Device code grant flow |
Revoke OAuth2 Token
POST/oauth2/token/revokeRevokes the given OAuth2 access or refresh token. Returns an empty object on success.
Form Params
| Field | Type | Description |
|---|---|---|
| token | string | The access or refresh token to revoke |
| client_id? 1 | snowflake | The ID of the application |
| client_secret? 1 2 | string | The client secret of the application |
1 You can also pass your client_id and client_secret as basic authentication with client_id as the username and client_secret as the password.
2 Not required if the application has the PUBLIC_OAUTH2_CLIENT application flag.
Get Provisional Account Token
POST/partner-sdk/tokenRetrieves an access token for a provisional account with the given credentials. Returns an OAuth2 access token object on success.
The response will only contain a refresh_token for OIDC when the application does not have the PUBLIC_OAUTH2_CLIENT application flag.
If an account isn't found but the provided external authentication token is valid, a new provisional account will be created.
Display Names
How are provisional account display names determined?
Display Names
How are provisional account display names determined?
- For bot-issued tokens, the
preferred_global_namespecified will be used. - For OIDC, a provisional account's display name will be the value of the
preferred_usernameclaim, if specified in the ID token. This field is optional and should be between 1 and 32 characters. If not specified, the user's display name will default to the user's unique username, which Discord generates on creation. - For Steam session tickets, the display name of the user's Steam account is used as the provisional account's display name.
- For EOS Auth Access Tokens or ID Tokens, the name of the user's Epic account is used as the provisional account's display name. EOS Connect ID Tokens do not expose any username, and thus the game will need to configure the display name manually.
- For Unity Services ID Tokens, the display name of the user's Unity Player Account is used as the provisional account's display name.
- For Apple ID Tokens, the name of the user's Apple ID account is used as the provisional account's display name.
- For PlayStation Network ID Tokens, the name of the user's PlayStation Network account is used as the provisional account's display name.
To change the display name of a provisional account, use the Modify Current User Account endpoint.
JSON Params
| Field | Type | Description |
|---|---|---|
| client_id | snowflake | The ID of the application |
| client_secret? 1 | string | The client secret of the application |
| external_auth_type | string | The type of the external authentication provider |
| external_auth_token | string | The external authentication token |
1 Not required if the application has the PUBLIC_OAUTH2_CLIENT application flag.
External Provider Authentication Type
| Value | Description |
|---|---|
| OIDC | OpenID Connect ID token |
| EPIC_ONLINE_SERVICES_ACCESS_TOKEN | Access token for Epic Online Services (supports EOS Auth access tokens) |
| EPIC_ONLINE_SERVICES_ID_TOKEN | ID token for Epic Online Services (supports both EOS Auth + Connect ID tokens) |
| STEAM_SESSION_TICKET | A Steam authentication ticket for web generated with discord set as the identity |
| UNITY_SERVICES_ID_TOKEN | ID token for Unity Auth Services |
| DISCORD_BOT_ISSUED_ACCESS_TOKEN | An access token for a user authenticated via a bot token |
| APPLE_ID_TOKEN | ID token for Apple ID |
| PLAYSTATION_NETWORK_ID_TOKEN | ID token for PlayStation Network |
Exchange Provisional Account Child Token
POST/partner-sdk/child-tokenExchanges a parent application token for a child application token. Returns an OAuth2 access token object on success.
JSON Params
| Field | Type | Description |
|---|---|---|
| child_application_id | snowflake | The ID of the child application |
| parent_access_token | string | The parent application token (max 10240 characters) |
Get Provisional Account Token with Bot
POST/partner-sdk/token/botRetrieves an access token for a provisional account with the given credentials. Returns an oauth2 access token object on success.
If an account isn't found, a new provisional account will be created.
JSON Params
| Field | Type | Description |
|---|---|---|
| external_user_id | string | The ID of the user to authenticate (max 1024 characters) |
| preferred_global_name? | string | The preferred global name for the user (1-32 characters) |
Unmerge Provisional Account
POST/partner-sdk/provisional-accounts/unmergeUnmerge a provisional account. Returns a 204 empty response on success.
JSON Params
| Field | Type | Description |
|---|---|---|
| client_id | snowflake | The ID of the application |
| client_secret? 1 | string | The client secret of the application |
| external_auth_type | string | The type of the external authentication provider |
| external_auth_token | string | The external authentication token |
1 Not required if the application has the PUBLIC_OAUTH2_CLIENT application flag.
Unmerge Provisional Account with Bot
POST/partner-sdk/provisional-accounts/unmerge/botUnmerge a provisional account. Returns a 204 empty response on success.
JSON Params
| Field | Type | Description |
|---|---|---|
| external_user_id | string | The ID of the user to unmerge (max 1024 characters) |
Get OAuth2 Authorizations
GET/oauth2/tokensReturns a list of OAuth2 authorization objects.
Get Application OAuth2 Authorizations
GET/oauth2/applications/{application.id}/tokensReturns a list of OAuth2 authorization objects for the given application ID.
Preview OAuth2 Authorization
GET/oauth2/authorizeReturns information about a possible OAuth2 authorization.
Query Params
| Field | Type | Description |
|---|---|---|
| client_id | snowflake | The ID of the application |
| response_type? 1 | string | The type of response to return |
| scope | string | A space-delimited list of scopes to request; may be omitted if the application has a populated integration_types_config |
| redirect_uri? 2 | string | The URL to redirect to after authorization; must match one of the registered redirect URIs for the application |
| state? | string | A unique string to bind the user's request to their authenticated state |
| nonce? | string | A unique string to bind the user's request to their authenticated state; only applicable for authorization code grants with the openid scope |
| code_challenge? | string | A code challenge for the PKCE extension to the authorization code grant; must be used with code_challenge_method |
| code_challenge_method? | string | The method used to generate the code challenge (must be S256); only applicable for the PKCE extension to the authorization code grant |
| integration_type? | integer | The installation context for the authorization; only applicable when scope contains applications.commands (default GUILD_INSTALL) |
1 Required unless the basic bot authorization flow is used.
2 If a response_type is specified and no redirect_uri is specified, the response will contain the first redirect URI registered for the application.
Response Body
| Field | Type | Description |
|---|---|---|
| application | partial application object | The application that is being authorized |
| user | partial user object | The user who is authorizing |
| authorized | boolean | Whether the user has already authorized the application with these scopes, meaning consent can be skipped |
| integration_type | integer | The installation context for the authorization |
| redirect_uri? | ?string | The URL to redirect to after authorization; only present if response_type is specified |
| bot? | partial user object | The bot user that will be added to the guild; only present the bot scope is requested |
| guilds? | array[oauth2 guild object] | The user's guilds; only present if integration_type is GUILD_INSTALL and the bot or applications.commands scope is requested |
OAuth2 Guild Structure
| Field | Type | Description |
|---|---|---|
| id | snowflake | The ID of the guild |
| name | string | The name of the guild (2-100 characters) |
| icon | ?string | The guild's icon hash |
| mfa_level | integer | Required MFA level for administrative actions within the guild |
| permissions | string | Permissions the user has in the guild |
Example OAuth2 Guild
{"id": "81384788765712384","name": "Discord API","icon": "a363a84e969bcbe1353eb2fdfb2e50e6","mfa_level": 1,"permissions": "1095530297282240"}
Create OAuth2 Authorization
POST/oauth2/authorizeAuthorizes the user for the given OAuth2 application. May fire a Guild Integrations Update, Integration Create, User Application Update, and/or User Connections Update Gateway event.
Query Params
| Field | Type | Description |
|---|---|---|
| client_id | snowflake | The ID of the application |
| response_type? 1 | string | The type of response to return |
| scope | string | A space-delimited list of scopes to request; may be omitted if the application has a populated integration_types_config |
| redirect_uri? 2 | string | The URL to redirect to after authorization; must match one of the registered redirect URIs for the application |
| state? | string | A unique string to bind the user's request to their authenticated state |
| nonce? | string | A unique string to bind the user's request to their authenticated state; only applicable for authorization code grants with the openid scope |
| code_challenge? | string | A code challenge for the PKCE extension to the authorization code grant; must be used with code_challenge_method |
| code_challenge_method? | string | The method used to generate the code challenge (must be S256); only applicable for the PKCE extension to the authorization code grant |
1 Required unless the basic bot authorization flow is used.
2 If a response_type is specified and no redirect_uri is specified, the user will be redirected to the first registered redirect URI for the application.
JSON Params
| Field | Type | Description |
|---|---|---|
| authorize? | boolean | Whether to authorize the user for the application (default false) |
| integration_type? | integer | The installation context for the authorization (default GUILD_INSTALL) |
| permissions? 1 | string | The permissions to request for the bot user in the guild; only applicable when the bot scope is requested |
| guild_id? | snowflake | The ID of the guild to which the application should be added or the webhook should be created; only applicable when the bot, applications.commands, or webhook.incoming scope is requested and integration_type is GUILD_INSTALL |
| webhook_channel_id? | snowflake | The ID of the channel where the webhook should be created; only applicable when the webhook.incoming scope is requested |
| dm_settings? | application DM settings object | The DM settings for the application; only applicable when the applications.commands scope is requested and integration_type is USER_INSTALL |
| location_context? | oauth2 location context object | The location context of the authorization within the client, used for analytics |
1 If no permissions are requested, an integration role is not created for the bot user in the guild.
Application DM Settings Structure
| Field | Type | Description |
|---|---|---|
| allow_mobile_push? | boolean | Whether to allow mobile push notifications for the application's DMs (default false) |
OAuth2 Location Context Structure
| Field | Type | Description |
|---|---|---|
| guild_id? | snowflake | The ID of the guild where the authorization is being created |
| channel_id? | snowflake | The ID of the channel where the authorization is being created |
| channel_type? | integer | The type of channel the authorization is being created in |
Response Body
| Field | Type | Description |
|---|---|---|
| url 1 | string | The URL to redirect the user to, containing the authorization code, access token, or error |
1 If a redirect_uri doesn't exist, https://discord.com will be used.
Get OAuth2 Authorization
GET/oauth2/tokens/{token.id}Returns an OAuth2 authorization for the given ID.
Delete OAuth2 Authorization
DELETE/oauth2/tokens/{token.id}Revokes the given authorization. Returns a 204 empty response on success. Fires multiple OAuth2 Token Revoke and optionally a User Application Remove and User Connections Update Gateway event.