Connect your Discord server to scripts and external applications. Read access and, since v1.1, write access (economy) protected by scopes. Available on Roody Pro and Team.
Generate a key in API keys and make your first request:
curl https://dashboard.roody.es/api/v1/me \ -H "Authorization: Bearer rdy_TU_CLAVE_AQUI"
Or in JavaScript:
const res = await fetch('https://dashboard.roody.es/api/v1/me', {
headers: { 'X-API-Key': 'rdy_TU_CLAVE_AQUI' }
});
const { data } = await res.json();
console.log(data.user.username, data.plan.tier);
Every request to /api/v1/* has to carry the key in one of these two headers:
Authorization: Bearer rdy_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx X-API-Key: rdy_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keys are personal, non-transferable, and never shown again after you create them — keep them in a secret manager. If a key is compromised, revoke it from your panel and create a new one.
Each key has a per-minute request limit that depends on the owner's plan. If you go over it, we return 429 with the Retry-After header.
Every response includes the X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers so your client knows how much you have left.
Returns the user who owns the key, their plan, the per-minute quota and the metadata of the key used in the request.
{
"success": true,
"data": {
"user": {
"discordId": "123456789012345678",
"username": "tu_usuario"
},
"plan": {
"tier": "pro",
"name": "Pro"
},
"rateLimit": {
"perMinute": 60,
"advanced": false
},
"apiKey": {
"prefix": "rdy_aB3xF2gH",
"label": "Mi script",
"createdAt": "2026-05-24T10:00:00.000Z",
"lastUsedAt": "2026-05-24T10:42:11.000Z"
}
}
}
Current bot status (online/connecting), number of servers and users, gateway ping and uptime in milliseconds.
{
"success": true,
"data": {
"status": "online",
"servers": 1284,
"users": 458321,
"ping": 41,
"uptimeMs": 184302000
}
}
Servers where the account owning the key is the owner or has "Administrator". Includes name, icon, member count and role.
{
"success": true,
"data": {
"count": 2,
"guilds": [
{
"id": "987654321098765432",
"name": "Mi servidor",
"icon": "https://cdn.discordapp.com/...",
"memberCount": 348,
"role": "owner"
},
{
"id": "876543210987654321",
"name": "Otro servidor",
"icon": null,
"memberCount": 1240,
"role": "admin"
}
]
}
}
Detailed server data: description, icon, banner, members, channels, roles, boost level, creation date, locale, features.
{
"success": true,
"data": {
"id": "987654321098765432",
"name": "Mi servidor",
"memberCount": 348,
"channels": 32,
"roles": 18,
"boost": {
"level": 2,
"count": 7
},
"owner": {
"id": "123456789012345678"
},
"role": "owner"
}
}
A summary of the server's enabled modules and whether they have a channel assigned: welcome, goodbye, boost, moderation, logs, giveaways, polls, tickets, antiraid, levels, economy.
{
"success": true,
"data": {
"guildId": "987654321098765432",
"lang": "es",
"modules": {
"bienvenidas": {
"enabled": true,
"hasChannel": true,
"type": "embed"
},
"moderacion": {
"enabled": true,
"antiflood": true,
"antilinks": false,
"antimayus": false
},
"economia": {
"enabled": false
}
}
}
}
Wallet, bank and basic economy data for a user in the server. Requires the economy:read scope (keys with * include it).
{
"success": true,
"data": {
"userId": "123456789012345678",
"cash": 1500,
"bank": 8000,
"total": 9500,
"level": 7,
"netWorth": 9500
}
}
Changes a user's balance. JSON body: { "action": "add" | "remove" | "set", "amount": number ≥ 0, "target": "cash" | "bank" (optional, cash by default) }. Requires the economy:write scope. add/remove are clamped to [0, 10,000,000,000].
{
"success": true,
"data": {
"userId": "123456789012345678",
"cash": 2500,
"bank": 8000,
"total": 10500,
"level": 7,
"netWorth": 9500,
"action": "add",
"target": "cash",
"applied": 1000
}
}
Turns a server module on or off. JSON body: { "enabled": true | false }. Supported modules: bienvenidas, despedidas, boost, logs, sorteos, polls, tickets, antiraid, niveles, economia. Requires the config:write scope.
{
"success": true,
"data": {
"guildId": "987654321098765432",
"module": "economia",
"enabled": true
}
}
Records a warning. JSON body: { "reason": "text" } (required). Requires the moderation:write scope.
{
"success": true,
"data": {
"userId": "123456789012345678",
"warnId": "A1B2C3",
"reason": "Spam en general",
"totalWarns": 2
}
}
Applies a timeout. JSON body: { "durationSeconds": 1..2419200, "reason": "text" (optional) }. The bot needs "Moderate Members" and has to sit above the user. Scope moderation:write.
{
"success": true,
"data": {
"userId": "123456789012345678",
"action": "timeout",
"durationSeconds": 3600,
"reason": "Flood"
}
}
Kicks the user. JSON body: { "reason": "text" (optional) }. The bot needs "Kick Members" and hierarchy over the user. Scope moderation:write.
{
"success": true,
"data": {
"userId": "123456789012345678",
"action": "kick",
"reason": "Saltarse las normas"
}
}
Bans the user (it also works as a pre-emptive ban if they are not in the server). JSON body: { "reason": "text" (optional), "deleteMessageSeconds": 0..604800 (optional) }. The bot needs "Ban Members". Scope moderation:write.
{
"success": true,
"data": {
"userId": "123456789012345678",
"action": "ban",
"reason": "Raid",
"deleteMessageSeconds": 86400
}
}
Complete examples of things you can automate. Switch language with the buttons and replace rdy_TU_CLAVE, GUILD_ID and USER_ID with your own.
Your site or game gives a member 500 coins when they complete an action. (scope economy:write)
curl -X POST https://dashboard.roody.es/api/v1/guilds/GUILD_ID/economy/users/USER_ID/balance \
-H "Authorization: Bearer rdy_TU_CLAVE" \
-H "Content-Type: application/json" \
-d '{"action":"add","amount":500,"target":"cash"}'
const res = await fetch(
'https://dashboard.roody.es/api/v1/guilds/GUILD_ID/economy/users/USER_ID/balance',
{
method: 'POST',
headers: {
'Authorization': 'Bearer rdy_TU_CLAVE',
'Content-Type': 'application/json'
},
body: JSON.stringify({ action: 'add', amount: 500, target: 'cash' })
}
);
const { data } = await res.json();
console.log('New balance:', data.cash);
import requests
res = requests.post(
'https://dashboard.roody.es/api/v1/guilds/GUILD_ID/economy/users/USER_ID/balance',
headers={'Authorization': 'Bearer rdy_TU_CLAVE'},
json={'action': 'add', 'amount': 500, 'target': 'cash'},
)
print('New balance:', res.json()['data']['cash'])
An anti-cheat or an external panel bans a cheater and deletes their messages from the last day. (scope moderation:write)
curl -X POST https://dashboard.roody.es/api/v1/guilds/GUILD_ID/members/USER_ID/ban \
-H "Authorization: Bearer rdy_TU_CLAVE" \
-H "Content-Type: application/json" \
-d '{"reason":"Cheating detected","deleteMessageSeconds":86400}'
await fetch(
'https://dashboard.roody.es/api/v1/guilds/GUILD_ID/members/USER_ID/ban',
{
method: 'POST',
headers: {
'Authorization': 'Bearer rdy_TU_CLAVE',
'Content-Type': 'application/json'
},
body: JSON.stringify({ reason: 'Cheating detected', deleteMessageSeconds: 86400 })
}
);
import requests
requests.post(
'https://dashboard.roody.es/api/v1/guilds/GUILD_ID/members/USER_ID/ban',
headers={'Authorization': 'Bearer rdy_TU_CLAVE'},
json={'reason': 'Cheating detected', 'deleteMessageSeconds': 86400},
)
Before an event, you disable the economy from your script and turn it back on afterwards. (scope config:write)
curl -X PATCH https://dashboard.roody.es/api/v1/guilds/GUILD_ID/config/economia \
-H "Authorization: Bearer rdy_TU_CLAVE" \
-H "Content-Type: application/json" \
-d '{"enabled":false}'
await fetch(
'https://dashboard.roody.es/api/v1/guilds/GUILD_ID/config/economia',
{
method: 'PATCH',
headers: {
'Authorization': 'Bearer rdy_TU_CLAVE',
'Content-Type': 'application/json'
},
body: JSON.stringify({ enabled: false })
}
);
import requests
requests.patch(
'https://dashboard.roody.es/api/v1/guilds/GUILD_ID/config/economia',
headers={'Authorization': 'Bearer rdy_TU_CLAVE'},
json={'enabled': False},
)
Show on your site how much money a member has. (scope economy:read)
curl https://dashboard.roody.es/api/v1/guilds/GUILD_ID/economy/users/USER_ID \ -H "Authorization: Bearer rdy_TU_CLAVE"
const res = await fetch(
'https://dashboard.roody.es/api/v1/guilds/GUILD_ID/economy/users/USER_ID',
{ headers: { 'Authorization': 'Bearer rdy_TU_CLAVE' } }
);
const { data } = await res.json();
console.log(`${data.cash} in wallet, ${data.bank} in bank`);
import requests
res = requests.get(
'https://dashboard.roody.es/api/v1/guilds/GUILD_ID/economy/users/USER_ID',
headers={'Authorization': 'Bearer rdy_TU_CLAVE'},
)
data = res.json()['data']
print(data['cash'], 'in wallet,', data['bank'], 'in bank')
If you make a lot of calls in a row, on a 429 wait the seconds given in Retry-After and retry.
# --retry retries and respects the Retry-After header curl --retry 3 --retry-delay 0 \ https://dashboard.roody.es/api/v1/me \ -H "Authorization: Bearer rdy_TU_CLAVE"
async function call(url, opts) {
for (let i = 0; i < 4; i++) {
const res = await fetch(url, opts);
if (res.status !== 429) return res;
const wait = Number(res.headers.get('Retry-After') || 1);
await new Promise(r => setTimeout(r, wait * 1000));
}
throw new Error('Rate limit: out of retries');
}
import time, requests
def call(method, url, **kw):
for _ in range(4):
res = requests.request(method, url, **kw)
if res.status_code != 429:
return res
time.sleep(int(res.headers.get('Retry-After', 1)))
raise RuntimeError('Rate limit: out of retries')
Every error follows the same shape: success: false + error.code + error.message.
{
"success": false,
"error": {
"code": "tier_insufficient",
"message": "This key belongs to a user without API access.",
"currentTier": "free",
"requiredTier": "pro"
}
}
The most common error codes:
| HTTP | code | When it happens |
|---|---|---|
| 401 | missing_api_key | The authentication header is missing. |
| 401 | invalid_api_key | Key not found or revoked. |
| 401 | expired_api_key | The key has expired. |
| 403 | tier_insufficient | The key's owner doesn't have Pro/Team. |
| 403 | guild_access_denied | The key's owner doesn't administer that server. |
| 403 | insufficient_scope | The key doesn't include the required scope (economy:write, for example). |
| 400 | invalid_action / invalid_amount / invalid_user_id | Invalid write parameters (economy). |
| 400 | invalid_module / invalid_body | Unsupported module or invalid body (config). |
| 404 | config_not_found | The server has no configuration. |
| 400 | invalid_reason / invalid_duration | The moderation parameters are missing or invalid. |
| 403 | target_is_owner / target_is_bot / hierarchy_error / bot_missing_permission | That user can't be moderated (owner, the bot itself, hierarchy, or the bot is missing a permission). |
| 404 | member_not_found | The user isn't in the server (for timeout/kick). |
| 502 | action_failed | Discord rejected the moderation action. |
| 404 | guild_not_found | The bot isn't in the requested server. |
| 404 | economy_user_not_found | The user has no economy data in that server. |
| 404 | endpoint_not_found | That endpoint doesn't exist in v1. |
| 429 | rate_limited | You have gone over your per-minute quota. |
| 503 | bot_unavailable | The bot is offline. |