Skip to content

Discord App Setup

Hails edited this page Jun 28, 2026 · 1 revision

Discord App Setup

These steps are completed once in the Discord Developer Portal.

1. Enable Social SDK Access

Open your application, go to Games > Social SDK, and submit the access form. Access is granted instantly.

2. Enable the Widget Editor Experiment

Open the Developer Portal in your browser, open the console (F12), and run:

let _mods = webpackChunkdiscord_developers.push([[Symbol()],{},r=>r.c]);
webpackChunkdiscord_developers.pop();

let findByProps = (...props) => {
    for (let m of Object.values(_mods)) {
        try {
            if (!m.exports || m.exports === window) continue;
            if (props.every((x) => m.exports?.[x])) return m.exports;
            for (let ex in m.exports) {
                if (props.every((x) => m.exports?.[ex]?.[x]) && m.exports[ex][Symbol.toStringTag] !== 'IntlMessagesProxy') return m.exports[ex];
            }
        } catch {}
    }
}

findByProps("getAll").getAll().find(e=>e.getName() === "ApexExperimentStore").createOverride("2026-03-widget-config-editor", 1)

Then click the back arrow and reopen your application without refreshing. A Widget page will appear under Games in the sidebar.

3. Create the Widget Layout

In the Widget editor, create your layout and map any of the User Data fields from the catalog. The Data Field names must match exactly. See Field Catalog for the full list of fields.

Discord allows at most 30 data fields per profile, but this service can produce 70+. Pick the fields you want (up to 30), map them here, and list those same names in ENABLED_FIELDS in your .env. See Field Catalog for details on the 30 field limit.

To preview every field with live values from your station (no Discord credentials required), run:

DRY_RUN=1 node sync.js

Save and Publish the widget when done.

4. OAuth2 Authorization

  1. Go to OAuth2 in the sidebar
  2. Add https://discord.com as a Redirect URI and save
  3. In the URL Generator, select the scopes openid and sdk.social_layer
  4. Select your redirect URI, copy the generated URL
  5. In the URL, change response_type=code to response_type=token
  6. Open the modified URL in your browser and authorize it

5. Issue Your Identity

Go to the Bot page, reset your token, and copy it. Then run the following in PowerShell, filling in your values:

$APP_ID    = "YOUR_APPLICATION_ID"
$USER_ID   = "YOUR_DISCORD_USER_ID"
$BOT_TOKEN = "YOUR_BOT_TOKEN"

$body = '{"username":"hails.live","data":{"dynamic":[{"type":1,"name":"track_title","value":"Sample Track"},{"type":1,"name":"artist","value":"Artist: Sample Artist"},{"type":2,"name":"listeners","value":0}]}}'

Invoke-RestMethod `
  -Uri "https://discord.com/api/v9/applications/$APP_ID/users/$USER_ID/identities/0/profile" `
  -Method PATCH `
  -Headers @{
    "Content-Type"  = "application/json"
    "Authorization" = "Bot $BOT_TOKEN"
    "User-Agent"    = "DiscordBot (https://github.com/discord/discord-api-docs, 1.0.0)"
  } `
  -Body $body

No output means success.

6. Add the Widget to Your Profile

In your Discord client, enable the renderer experiment by running this in the console (wrap in braces if you see a redeclaration error):

{
    let _mods = webpackChunkdiscord_app.push([[Symbol()],{},r=>r.c]);
    webpackChunkdiscord_app.pop();
    let findByProps = (...props) => {
        for (let m of Object.values(_mods)) {
            try {
                if (!m.exports || m.exports === window) continue;
                if (props.every((x) => m.exports?.[x])) return m.exports;
                for (let ex in m.exports) {
                    if (props.every((x) => m.exports?.[ex]?.[x]) && m.exports[ex][Symbol.toStringTag] !== 'IntlMessagesProxy') return m.exports[ex];
                }
            } catch {}
        }
    }
    findByProps("getAll").getAll().find(e=>e.getName() === "ApexExperimentStore").createOverride("2026-03-application-widget-v2-renderer", 1)
}

Then add the widget to your profile. If you have Vencord installed:

async function addWidget(appId) {
    id = Vencord.Webpack.findByProps("getCurrentUser").getCurrentUser().id;
    current_widgets = (await Vencord.Webpack.Common.RestAPI.get("/users/" + id + "/profile")).body.widgets
    if (current_widgets.map(x=>x.data?.application_id).includes(appId)) {
        return console.log("Already in your widgets");
    }
    current_widgets.unshift({"data":{"type":"application","application_id":appId}})
    await Vencord.Webpack.Common.RestAPI.put({url:"/users/@me/widgets",body:{widgets:current_widgets}})
}
addWidget("YOUR_APPLICATION_ID")

For other methods, check the Discord Previews server thread for ready-to-run snippets.

For the full list of mappable fields, see Field Catalog. For optional .env settings such as ENABLED_FIELDS, see Configuration.

Clone this wiki locally