Roody API REST v1

Integra tu servidor de Discord con scripts y aplicaciones externas. Lectura y, desde v1.1, escritura (economía) protegida por scopes. Disponible para Roody Pro y Team.

Arranca rápido

Genera una clave en Claves de API y haz tu primera petición:

curl https://dashboard.roody.es/api/v1/me \
  -H "Authorization: Bearer rdy_TU_CLAVE_AQUI"

O en 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);

Autenticación

Toda petición a /api/v1/* debe llevar la clave en uno de estos dos headers:

Authorization: Bearer rdy_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
X-API-Key:     rdy_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Las claves son personales, intransferibles y nunca se vuelven a mostrar tras crearlas — guárdalas en un gestor de secretos. Si una clave se compromete, revócala desde tu panel y crea otra.

Cuotas por plan

Cada clave tiene un límite de peticiones por minuto que depende del plan del dueño. Si lo superas, devolvemos 429 con el header Retry-After.

Pro
60 req/min
Suficiente para sincronizar dashboards o cron jobs.
Team
600 req/min
Para integraciones multi-servidor y herramientas en producción.

Cada respuesta incluye headers X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset para que tu cliente sepa cuánto te queda.

Endpoints

GET /api/v1/me Datos de la cuenta

Devuelve el usuario dueño de la clave, su plan, la cuota por minuto y los metadatos de la clave usada en la petición.

{
  "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"
    }
  }
}
GET /api/v1/bot/status Estado del bot

Estado actual del bot (online/connecting), número de servidores y usuarios, ping al gateway y uptime en milisegundos.

{
  "success": true,
  "data": {
    "status": "online",
    "servers": 1284,
    "users": 458321,
    "ping": 41,
    "uptimeMs": 184302000
  }
}
GET /api/v1/guilds Lista de servidores

Servidores donde la cuenta dueña de la clave es propietaria o tiene "Administrator". Incluye nombre, icono, nº de miembros y rol.

{
  "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"
      }
    ]
  }
}
GET /api/v1/guilds/:id Información de un servidor

Datos detallados del servidor: descripción, icono, banner, miembros, canales, roles, nivel de boost, fecha de creación, 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"
  }
}
GET /api/v1/guilds/:id/config Configuración del servidor

Resumen de los módulos activos del servidor y si tienen canal asignado: bienvenidas, despedidas, boost, moderación, logs, sorteos, polls, tickets, antiraid, niveles, economía.

{
  "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
      }
    }
  }
}
GET /api/v1/guilds/:id/economy/users/:userId Saldo de un usuario (economía)

Cartera, banco y datos básicos de economía de un usuario en el servidor. Requiere el scope economy:read (las claves con * lo incluyen).

{
  "success": true,
  "data": {
    "userId": "123456789012345678",
    "cash": 1500,
    "bank": 8000,
    "total": 9500,
    "level": 7,
    "netWorth": 9500
  }
}
POST /api/v1/guilds/:id/economy/users/:userId/balance Ajustar saldo (escritura)

Modifica el saldo de un usuario. Body JSON: { "action": "add" | "remove" | "set", "amount": número ≥ 0, "target": "cash" | "bank" (opcional, por defecto cash) }. Requiere el scope economy:write. add/remove se acotan a [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
  }
}
PATCH /api/v1/guilds/:id/config/:module Activar/desactivar un módulo (escritura)

Enciende o apaga un módulo del servidor. Body JSON: { "enabled": true | false }. Módulos soportados: bienvenidas, despedidas, boost, logs, sorteos, polls, tickets, antiraid, niveles, economia. Requiere el scope config:write.

{
  "success": true,
  "data": {
    "guildId": "987654321098765432",
    "module": "economia",
    "enabled": true
  }
}
POST /api/v1/guilds/:id/members/:userId/warn Avisar a un usuario (moderación)

Registra un warning. Body JSON: { "reason": "texto" } (obligatorio). Requiere el scope moderation:write.

{
  "success": true,
  "data": {
    "userId": "123456789012345678",
    "warnId": "A1B2C3",
    "reason": "Spam en general",
    "totalWarns": 2
  }
}
POST /api/v1/guilds/:id/members/:userId/timeout Aislar a un usuario (moderación)

Aplica un timeout. Body JSON: { "durationSeconds": 1..2419200, "reason": "texto" (opcional) }. El bot necesita "Moderar miembros" y estar por encima del usuario. Scope moderation:write.

{
  "success": true,
  "data": {
    "userId": "123456789012345678",
    "action": "timeout",
    "durationSeconds": 3600,
    "reason": "Flood"
  }
}
POST /api/v1/guilds/:id/members/:userId/kick Expulsar a un usuario (moderación)

Expulsa al usuario. Body JSON: { "reason": "texto" (opcional) }. El bot necesita "Expulsar miembros" y jerarquía sobre el usuario. Scope moderation:write.

{
  "success": true,
  "data": {
    "userId": "123456789012345678",
    "action": "kick",
    "reason": "Saltarse las normas"
  }
}
POST /api/v1/guilds/:id/members/:userId/ban Banear a un usuario (moderación)

Banea al usuario (también sirve como ban preventivo si no está en el servidor). Body JSON: { "reason": "texto" (opcional), "deleteMessageSeconds": 0..604800 (opcional) }. El bot necesita "Banear miembros". Scope moderation:write.

{
  "success": true,
  "data": {
    "userId": "123456789012345678",
    "action": "ban",
    "reason": "Raid",
    "deleteMessageSeconds": 86400
  }
}

Usos reales

Ejemplos completos de cosas que puedes automatizar. Cambia de lenguaje con los botones y sustituye rdy_TU_CLAVE, GUILD_ID y USER_ID por los tuyos.

1. Recompensar a un usuario

Tu web/juego da 500 monedas a un miembro cuando completa una acción. (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('Nuevo saldo:', 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('Nuevo saldo:', res.json()['data']['cash'])

2. Banear desde tu propio panel

Un anti-cheat o panel externo banea a un tramposo y borra sus mensajes del último día. (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":"Trampas detectadas","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: 'Trampas detectadas', 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': 'Trampas detectadas', 'deleteMessageSeconds': 86400},
)

3. Apagar un módulo en mantenimiento

Antes de un evento, desactivas la economía desde tu script y la vuelves a activar al terminar. (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},
)

4. Consultar el saldo de un usuario

Muestra en tu web cuánto dinero tiene un miembro. (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} en cartera, ${data.bank} en banco`);
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'], 'en cartera,', data['bank'], 'en banco')

5. Respetar el límite de peticiones (429)

Si haces muchas llamadas seguidas, ante un 429 espera los segundos de Retry-After y reintenta.

# --retry reintenta y respeta el header Retry-After
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: reintentos agotados');
}
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: reintentos agotados')

Formato de errores

Todos los errores siguen el mismo formato: success: false + error.code + error.message.

{
  "success": false,
  "error": {
    "code": "tier_insufficient",
    "message": "Esta clave pertenece a un usuario sin acceso a la API.",
    "currentTier": "free",
    "requiredTier": "pro"
  }
}

Códigos de error más comunes:

HTTPcodeCuándo ocurre
401missing_api_keyFalta el header de autenticación.
401invalid_api_keyClave no encontrada o revocada.
401expired_api_keyLa clave ha caducado.
403tier_insufficientEl dueño de la clave no tiene Pro/Team.
403guild_access_deniedEl dueño de la clave no administra ese servidor.
403insufficient_scopeLa clave no incluye el scope necesario (p. ej. economy:write).
400invalid_action / invalid_amount / invalid_user_idParámetros de escritura inválidos (economía).
400invalid_module / invalid_bodyMódulo no soportado o body inválido (config).
404config_not_foundEl servidor no tiene configuración.
400invalid_reason / invalid_durationFaltan o son inválidos los parámetros de moderación.
403target_is_owner / target_is_bot / hierarchy_error / bot_missing_permissionNo se puede moderar a ese usuario (dueño, el propio bot, jerarquía o falta de permiso del bot).
404member_not_foundEl usuario no está en el servidor (para timeout/kick).
502action_failedDiscord rechazó la acción de moderación.
404guild_not_foundEl bot no está en el servidor pedido.
404economy_user_not_foundEl usuario no tiene economía en ese servidor.
404endpoint_not_foundEndpoint no existe en v1.
429rate_limitedHas superado tu cuota por minuto.
503bot_unavailableEl bot está desconectado.