Building a Discord role whitelist for FiveM
Most whitelisted roleplay servers accept players through a Discord application, then give them a role. A small server script can check that role while the player connects and turn everyone else away with a helpful message. It needs a Discord bot, the player’s Discord identifier and connection deferrals.
Short answer: In playerConnecting, call deferrals.defer(), read the player’s discord identifier, and ask the Discord API (GET /guilds/{guild}/members/{user} with your bot token) whether they are in the guild and hold the whitelist role. Call deferrals.done() to let them in or deferrals.done('reason') to refuse. Keep the bot token in a server-only convar and cache results briefly.

#Step 1: create the Discord bot
- In the Discord Developer Portal, create an application and add a bot; copy its token.
- Invite the bot to your Discord server (it only needs to read members; no admin rights).
- Enable Developer Mode in Discord and copy your guild ID and the whitelist role ID.
set wl_botToken "your-bot-token"
set wl_guildId "123456789012345678"
set wl_roleId "234567890123456789"#Step 2: the connection check
local TOKEN = GetConvar('wl_botToken', '')
local GUILD = GetConvar('wl_guildId', '')
local ROLE = GetConvar('wl_roleId', '')
local JOIN = 'https://discord.gg/yourinvite'
local function hasRole(discordId)
local p = promise.new()
PerformHttpRequest(('https://discord.com/api/v10/guilds/%s/members/%s'):format(GUILD, discordId), function(status, body)
if status ~= 200 then return p:resolve(status == 404 and 'notmember' or 'error') end
local member = json.decode(body)
for _, r in ipairs(member.roles or {}) do
if r == ROLE then return p:resolve('ok') end
end
p:resolve('norole')
end, 'GET', '', { Authorization = 'Bot ' .. TOKEN })
return Citizen.Await(p)
end
AddEventHandler('playerConnecting', function(name, setKickReason, deferrals)
local src = source
deferrals.defer()
Wait(0)
deferrals.update('Checking your Discord whitelist…')
local id = GetPlayerIdentifierByType(src, 'discord')
if not id then
return deferrals.done('Open Discord and restart FiveM so we can see your account. Join: ' .. JOIN)
end
local result = hasRole((id:gsub('discord:', '')))
if result == 'ok' then
deferrals.done()
elseif result == 'notmember' then
deferrals.done('You are not in our Discord yet. Join and apply: ' .. JOIN)
elseif result == 'norole' then
deferrals.done('You are not whitelisted yet. Apply in our Discord: ' .. JOIN)
else
deferrals.done('Whitelist check failed, please try again in a minute.')
end
end)#Caching and rate limits
Discord rate-limits bots. Cache positive results for a few minutes per Discord ID so reconnect loops do not hammer the API, and decide what happens during a Discord outage (refuse with a clear message, or allow players you saw recently).
#Make refusals helpful
- Say exactly what is missing: Discord not linked, not in the guild, or no role.
- Include the invite link and where to apply.
- For a richer screen with buttons and links, show an adaptive card with
deferrals.presentCardinstead of plain text.
#Ready-made options
Many frameworks and txAdmin include whitelist features (txAdmin has its own approval-based whitelist), and there are established Discord permission resources. Writing your own is worth it when you want custom messages or several roles; otherwise a maintained resource saves time.
Questions
How do I whitelist my FiveM server with Discord?
playerConnecting with a bot and the Discord API, and refuse the connection with deferrals.done(reason) if the role is missing.Why does the whitelist say my Discord is not linked?
Is it safe to put my bot token in server.cfg?
set (server-only). Never use setr, which sends the value to clients.Why are players stuck on Connecting?
deferrals.done. Make sure every branch finishes the deferral.Does txAdmin have a whitelist?
Ready to pick a map?
Twelve themes on three base map styles, $8 each, instant download.