Aether Panel Documentation
Introducción a la API
La API de Aether Panel (SkyPanel) es una API RESTful completa y potente que permite la automatización y gestión programática de todos los aspectos del panel. Está diseñada siguiendo los estándares de la industria y soporta OAuth2 para autenticación segura.
Con esta API puedes automatizar completamente la gestión de servidores, usuarios, nodos, bases de datos, backups y mucho más. Ideal para integraciones con sistemas de facturación, paneles de control personalizados, bots de Discord, o cualquier aplicación que necesite interactuar con Aether Panel.
Todas las peticiones a la API deben realizarse a la siguiente URL base:
http://tu-servidor:8080/apihttps://panel.tudominio.com/api
En desarrollo, usa la IP o localhost. En producción, siempre usa HTTPS para seguridad.
La API está versionada para garantizar compatibilidad. La versión actual es v1. Todas las respuestas incluyen el header `X-API-Version` con la versión de la API utilizada.
Las solicitudes a la API se autentican mediante Bearer Tokens. Puedes generar claves de API desde la configuración de tu cuenta en el panel. Todas las solicitudes a la API deben realizarse a través de HTTPS.
- RESTful: Sigue principios REST estándar
- OAuth2: Autenticación segura con tokens
- JSON: Formato de datos JSON para requests y responses
- Versionada: API versionada para compatibilidad
- Documentada: Documentación completa con ejemplos
- WebSocket: Soporte para comunicación en tiempo real
- Paginación: Resultados paginados para grandes conjuntos de datos
- Filtrado: Búsqueda y filtrado avanzado
https://dominio:8080/apiSkyPanel utiliza OAuth2 con el flujo de **Client Credentials** para autenticación de API.
Puedes crear un cliente OAuth2 desde:
- Panel Web: Configuración → OAuth2 Clients
- CLI: `skypanel oauth2 create`
Endpoint
POST /oauth2/tokenHeaders
http Content-Type: application/x-www-form-urlencodedBody
grant_type=client_credentials client_id=TU_CLIENT_ID client_secret=TU_CLIENT_SECRETEjemplo con cURL
curl -X POST http://localhost:8080/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"Respuesta
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "server.view server.edit"
}Incluye el token en el header `Authorization` de todas las peticiones:.
http Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Ejemplo
curl -X GET http://localhost:8080/api/servers -H "Authorization: Bearer YOUR_ACCESS_TOKEN"Scopes definen los permisos que un cliente tiene para acceder a ciertos endpoints. Por ejemplo, un cliente con el scope `server.read` puede leer información de servidores, pero no puede crear o modificarlos.
| Permiso | Descripción |
|---|---|
| admin | Acceso administrativo completo |
| server.view | Ver servidores |
| server.create | Crear servidores |
| server.edit | Editar servidores |
| server.delete | Eliminar servidores |
| server.start | Iniciar servidores |
| server.stop | Detener servidores |
| server.console | Acceso a consola |
| server.files.view | Ver archivos |
| server.files.edit | Editar archivos |
| users.view | Ver usuarios |
| users.edit | Editar usuarios |
| nodes.view | Ver nodos |
| nodes.edit | Editar nodos |
Todas las peticiones y respuestas usan JSON:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "server.view server.edit"
}{
"data": { ... },
"metadata": {
"paging": {
"page": 1,
"size": 25,
"maxSize": 100,
"total": 150
}
}
}| Código | Significado | Descripción |
|---|---|---|
| 200 | OK | Petición exitosa |
| 201 | Created | Recurso creado exitosamente |
| 204 | No Content | Petición exitosa sin contenido de respuesta |
| 400 | Bad Request | Datos de entrada inválidos |
| 401 | Unauthorized | Token inválido o expirado |
| 403 | Forbidden | Sin permisos para esta acción |
| 404 | Not Found | Recurso no encontrado |
| 500 | Internal Server Error | Error del servidor |
{
"error": {
"code": "ErrServerNotFound",
"msg": "Server with ID {id} not found",
"metadata": {
"id": "ABC12345"
}
}
}| Código | Descripción |
|---|---|
| ErrFieldRequired | Campo requerido faltante |
| ErrFieldInvalid | Valor de campo inválido |
| ErrServerNotFound | Servidor no encontrado |
| ErrUserNotFound | Usuario no encontrado |
| ErrNodeNotFound | Nodo no encontrado |
| ErrPermissionDenied | Permiso denegado |
| ErrDatabaseError | Error de base de datos |
Paginación
Los endpoints que retornan listas soportan paginación:
| Parámetro | Tipo | Default | Descripción |
|---|---|---|---|
| page | int | 1 | Número de página (1-indexed) |
| limit | int | 25 | Elementos por página |
Máximo: 100 elementos por página
GET /api/servers?page=2&limit=50{
"servers": [...],
"metadata": {
"paging": {
"page": 2,
"size": 50,
"maxSize": 100,
"total": 237
}
}
}Endpoints de Servidores
Endpoint: GET /api/servers
Scopes: server.view
| Parámetro | Tipo | Descripción |
|---|---|---|
| username | string | Filtrar por usuario (solo admin) |
| node | uint | Filtrar por ID de nodo |
| name | string | Filtrar por nombre (soporta * como wildcard) |
| page | uint | Número de página |
| limit | uint | Elementos por página |
curl -X GET "http://localhost:8080/api/servers?username=admin*" \
-H "Authorization: Bearer YOUR_TOKEN"{
"servers": [
{
"id": 1,
"uuid": "abc12345...",
"name": "Survival Server",
"ownerId": 1,
"nodeId": 1,
"image": "ghcr.io/pterodactyl/yolks:java_17",
"startup": "java -Xms128M -Xmx1024M -jar server.jar"
}
],
"metadata": {
"paging": {
"page": 1,
"size": 25,
"maxSize": 100,
"total": 1
}
}
}Endpoint: GET /api/servers/:serverId
Scopes: server.view
| Parámetro | Tipo | Ubicación | Descripción |
|---|---|---|---|
| serverId | string | Path | ID del servidor |
| perms | boolean | Query | Incluir permisos del usuario |
{
"id": 1,
"uuid": "abc12345...",
"name": "Survival Server",
"ownerId": 1,
"nodeId": 1,
"status": "installing",
"resources": {
"memory": 1024,
"disk": 5120,
"cpu": 100
},
"deployment": {
"port": 25565,
"ip": "192.168.1.1"
}
}Endpoint: PUT /api/servers/:serverId
Scopes: server.create
{
"name": "New Server",
"ownerId": 1,
"eggId": 1,
"dockerImage": "ghcr.io/pterodactyl/yolks:java_17",
"startup": "java -Xms128M -Xmx{{SERVER_MEMORY}}M -jar {{SERVER_JARFILE}}",
"environment": {
"SERVER_JARFILE": "server.jar",
"f": "v"
},
"limits": {
"memory": 1024,
"swap": 0,
"disk": 5120,
"io": 500,
"cpu": 100
},
"featureLimits": {
"databases": 1,
"backups": 1
}
}{
"id": 2,
"uuid": "def67890...",
"name": "New Server",
"status": "installing"
}Endpoint: PUT /api/servers/:serverId/definition
Scopes: server.definition.edit
{
"name": "Nuevo Nombre",
"type": {
"type": "minecraft-java"
},
"icon": "nuevo-icono.png",
"server": {
"run": {
"command": "java -Xmx4G -jar server.jar nogui"
},
"data": {
"memory": 4096
}
},
"variables": {
"port": 25566
}
}Respuesta: 204 No Content
Endpoint: DELETE /api/servers/:serverId
Scopes: server.delete
| Parámetro | Tipo | Descripción |
|---|---|---|
| skipNode | boolean | No eliminar del nodo, solo de la base de datos |
Respuesta: 204 No Content
Endpoint: POST /api/servers/:serverId/start
Scopes: server.start
Respuesta: 204 No Content
Endpoint: POST /api/servers/:serverId/stop
Scopes: server.stop
Respuesta: 204 No Content
Endpoint: POST /api/servers/:serverId/restart
Scopes: server.start, server.stop
Respuesta: 204 No Content
Endpoint: POST /api/servers/:serverId/kill
Scopes: server.kill
Respuesta: 204 No Content
Endpoint: POST /api/servers/:serverId/install
Scopes: server.install
Respuesta: 204 No Content
Endpoint: GET /api/servers/:serverId/status
Scopes: server.status
{
"running": true
}Endpoint: GET /api/servers/:serverId/stats
Scopes: server.stats
{
"cpu": 45.2,
"memory": 1536000000,
"memoryTotal": 2147483648
}Endpoint: GET /api/servers/:serverId/console
Scopes: server.console
| Parámetro | Tipo | Descripción |
|---|---|---|
| time | int | Timestamp desde el cual obtener logs |
{
"logs": [
"[10:30:15] [Server thread/INFO]: Starting minecraft server version 1.20.1",
"[10:30:16] [Server thread/INFO]: Loading properties"
]
}Endpoint: POST /api/servers/:serverId/console
Scopes: server.sendCommand
{
"command": "say Hello World!"
}Respuesta: 204 No Content
Gestión de Archivos
Endpoint: GET /api/servers/:serverId/file/*filename
Scopes: server.files.view
curl -X GET "http://localhost:8080/api/servers/ABC12345/file/" \
-H "Authorization: Bearer YOUR_TOKEN"{
"files": [
{
"name": "server.jar",
"size": 45678901,
"modified": "2024-01-15T10:30:00Z",
"isFile": true
},
{
"name": "world",
"size": 0,
"modified": "2024-01-15T10:25:00Z",
"isFile": false
}
]
}Endpoint: GET /api/servers/:serverId/file/*filename
Scopes: server.files.view
curl -X GET "http://localhost:8080/api/servers/ABC12345/file/server.properties" \
-H "Authorization: Bearer YOUR_TOKEN" \
-o server.propertiesEndpoint: PUT /api/servers/:serverId/file/*filename
Scopes: server.files.edit
curl -X PUT "http://localhost:8080/api/servers/ABC12345/file/config.yml" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/octet-stream" \
--data-binary @config.ymlEndpoint: DELETE /api/servers/:serverId/file/*filename
Scopes: server.files.edit
curl -X DELETE "http://localhost:8080/api/servers/ABC12345/file/old-backup.zip" \
-H "Authorization: Bearer YOUR_TOKEN"Backups
Endpoint: GET /api/servers/:serverId/backup
Scopes: server.backup.view
{
"backups": [
{
"id": "backup-20240115-103000",
"size": 123456789,
"created": "2024-01-15T10:30:00Z"
}
]
}Endpoint: POST /api/servers/:serverId/backup/create
Scopes: server.backup.create
{
"id": "backup-20240115-120000"
}Endpoint: POST /api/servers/:serverId/backup/restore/:backupId
Scopes: server.backup.restore
Respuesta: 204 No Content
Endpoint: DELETE /api/servers/:serverId/backup/:backupId
Scopes: server.backup.delete
Respuesta: 204 No Content
Endpoint: GET /api/servers/:serverId/backup/download/:backupId
Scopes: server.backup.view
curl -X GET "http://localhost:8080/api/servers/ABC12345/backup/download/backup-20240115-103000" \
-H "Authorization: Bearer YOUR_TOKEN" \
-o backup.tar.gzUsuarios
Endpoint: GET /api/users
Scopes: users.info.search
curl -X GET "http://localhost:8080/api/users?username=admin*" \
-H "Authorization: Bearer YOUR_TOKEN"Endpoint: POST /api/users
Scopes: users.info.edit
{
"username": "newuser",
"email": "newuser@example.com",
"password": "SecurePassword123!"
}Endpoint: GET /api/users/:id
Scopes: users.info.view
Endpoint: POST /api/users/:id
Scopes: users.info.edit
Endpoint: DELETE /api/users/:id
Scopes: users.info.edit
Respuesta: 204 No Content
Endpoint: GET /api/users/:id/perms
Scopes: users.perms.view
[
"server.view",
"server.console"
]Endpoint: PUT /api/users/:id/perms
Scopes: users.perms.edit
{
"scopes": [
"server.view",
"server.console",
"server.files.view",
"server.files.edit"
]
}Respuesta: 204 No Content
Nodos
Endpoint: GET /api/nodes
Scopes: nodes.view
[
{
"id": 1,
"name": "Node-01",
"publicHost": "node1.example.com"
}
]Endpoint: POST /api/nodes
Scopes: nodes.create
{
"name": "Node-02",
"publicHost": "node2.example.com",
"privateHost": "192.168.1.11",
"publicPort": 8080,
"privatePort": 8080,
"sftpPort": 5657
}{
"id": 2,
"name": "Node-02",
"publicHost": "node2.example.com",
"privateHost": "192.168.1.11",
"publicPort": 8080,
"privatePort": 8080,
"sftpPort": 5657,
"secret": "abc123def456..."
}Endpoint: GET /api/nodes/:id
Scopes: nodes.view
{
"id": 1,
"name": "Node-01",
"publicHost": "node1.example.com",
"privateHost": "192.168.1.10",
"publicPort": 8080,
"privatePort": 8080,
"sftpPort": 5657
}Endpoint: PUT /api/nodes/:id
Scopes: nodes.edit
{
"name": "Node-01-Updated",
"publicHost": "node1-new.example.com"
}Respuesta: 204 No Content
Endpoint: DELETE /api/nodes/:id
Scopes: nodes.delete
Respuesta: 204 No Content
Endpoint: GET /api/nodes/:id/system
Scopes: nodes.view
{
"cpu": {
"model": "Intel(R) Xeon(R) CPU E5-2680 v4",
"cores": 8,
"threads": 16,
"mhz": 2400.0
},
"memory": {
"total": 17179869184,
"used": 8589934592,
"free": 8589934592
},
"disk": {
"total": 1099511627776,
"used": 549755813888,
"free": 549755813888
},
"os": {
"platform": "linux",
"family": "debian",
"version": "22.04"
}
}Endpoint: GET /api/nodes/:id/features
Scopes: nodes.view
{
"docker": true,
"environments": [
"standard",
"docker"
]
}Endpoint: GET /api/nodes/:id/deployment
Scopes: nodes.deploy
{
"clientId": ".node_1",
"clientSecret": "abc123def456..."
}Configuración
Endpoint: GET /api/settings
Scopes: settings.view
{
"companyName": "SkyPanel",
"defaultTheme": "SkyPanel",
"masterUrl": "https://panel.example.com",
"registrationEnabled": false
}Endpoint: PUT /api/settings
Scopes: settings.edit
{
"companyName": "Mi Empresa",
"registrationEnabled": true
}Respuesta: 204 No Content
Plantillas
Endpoint: GET /api/templates
Scopes: templates.view
{
"templates": [
{
"name": "minecraft-java",
"display": "Minecraft Java Edition",
"type": "java",
"supportedVersions": ["1.20.1", "1.19.4", "1.18.2"]
},
{
"name": "terraria",
"display": "Terraria",
"type": "native",
"supportedVersions": ["1.4.4.9"]
}
]
}Endpoint: GET /api/templates/:name
Scopes: templates.view
{
"name": "minecraft-java",
"display": "Minecraft Java Edition",
"type": "java",
"install": [
{
"type": "mojangdl",
"version": "{{version}}"
}
],
"run": {
"command": "java -Xmx{{memory}}M -jar server.jar nogui",
"stop": "stop"
},
"variables": {
"version": {
"type": "string",
"default": "1.20.1",
"required": true
},
"memory": {
"type": "integer",
"default": 2048,
"required": true
}
}
}WebSocket API
Endpoint: WS /api/servers/:serverId/socket
Protocol: WebSocket
Scopes: server.view
const ws = new WebSocket(`ws://localhost:8080/api/servers/${serverId}/socket`);
ws.onopen = () => {
ws.send(JSON.stringify({ type: 'auth', token: 'YOUR_TOKEN' }));
};
ws.onmessage = (event) => {
console.log('Message:', JSON.parse(event.data));
};- Autenticación: { "type": "auth", "token": "..." }
- Consola (Servidor -> Cliente): { "type": "console", "data": "..." }
- Comando (Cliente -> Servidor): { "type": "console", "data": "command" }
- Estadísticas (Servidor -> Cliente): { "type": "stats", "data": { ... } }
- Estado (Servidor -> Cliente): { "type": "status", "data": { ... } }
Bases de Datos de Servidor
Estos endpoints permiten gestionar bases de datos MySQL/MariaDB asociadas a servidores específicos.
Endpoint: GET /api/servers/:serverId/databases
Scopes: server.view
Obtiene todas las bases de datos creadas para un servidor específico.
Endpoint: POST /api/servers/:serverId/databases
Scopes: server.edit
Crea una nueva base de datos MySQL/MariaDB para el servidor. El panel genera automáticamente el nombre de la base de datos, usuario y contraseña.
databaseHostId: ID del Database Host a usar (requerido)databaseName: Nombre personalizado de la base de datos (opcional, se genera automáticamente si se omite)
Endpoint: DELETE /api/servers/:serverId/databases/:databaseId
Scopes: server.edit
Elimina una base de datos y su usuario asociado del servidor MySQL/MariaDB.
Database Hosts
Los Database Hosts son configuraciones de servidores MySQL/MariaDB que el panel puede usar para crear bases de datos automáticamente.
Endpoint: GET /api/databasehosts
Scopes: admin
Obtiene todos los Database Hosts configurados en el panel.
Endpoint: POST /api/databasehosts
Scopes: admin
Crea un nuevo Database Host. Requiere credenciales de MySQL con permisos GRANT ALL PRIVILEGES.
name: Nombre del host (requerido)host: IP o dominio del servidor MySQL (requerido)port: Puerto MySQL (por defecto 3306)username: Usuario MySQL con permisos (requerido)password: Contraseña del usuario (requerido)maxDatabases: Máximo número de bases de datos (opcional, sin límite si se omite)nodeId: ID del nodo vinculado (opcional)
Límites de Tasa (Rate Limiting)
La API implementa límites de tasa para prevenir abuso y asegurar un rendimiento óptimo para todos los usuarios.
- Autenticado: 1000 peticiones por hora por cliente OAuth2
- No autenticado: 100 peticiones por hora por IP
Los límites se aplican por cliente OAuth2 o por IP para peticiones no autenticadas.
Mejores Prácticas
Sigue estas recomendaciones para usar la API de manera eficiente y segura:
- Usa HTTPS en producción: Nunca envíes tokens o credenciales a través de HTTP sin cifrar.
- Almacena tokens de forma segura: No hardcodees tokens en tu código. Usa variables de entorno o sistemas de gestión de secretos.
- Maneja errores apropiadamente: Siempre verifica los códigos de estado HTTP y maneja errores de forma elegante.
- Implementa reintentos con backoff exponencial: Para peticiones que fallan temporalmente, implementa lógica de reintento.
- Usa paginación para listas grandes: No intentes obtener todos los resultados de una vez. Usa paginación para mejorar el rendimiento.
- Cachea respuestas cuando sea apropiado: Algunos datos no cambian frecuentemente y pueden ser cacheados.
- Respeta los límites de tasa: Implementa throttling en tu aplicación para no exceder los límites.
- Valida datos antes de enviarlos: Verifica que los datos cumplen con los requisitos antes de hacer peticiones.
- Usa WebSockets para datos en tiempo real: Para consolas y estadísticas, usa WebSockets en lugar de polling constante.
- Mantén tus tokens seguros: Rota tus client secrets regularmente y nunca los compartas públicamente.
Solución de Problemas
Error 401 Unauthorized
Tu token ha expirado o es inválido. Obtén un nuevo token usando el endpoint /oauth2/token.
Error 403 Forbidden
Tu cliente OAuth2 no tiene los scopes necesarios para esta acción. Verifica los scopes asignados a tu cliente.
Error 404 Not Found
El recurso que intentas acceder no existe. Verifica que el ID sea correcto y que el recurso no haya sido eliminado.
Error 400 Bad Request
Los datos enviados no son válidos. Revisa la estructura del body y los tipos de datos requeridos.
Error 429 Too Many Requests
Has excedido el límite de tasa. Espera hasta que se reinicie el contador o implementa throttling en tu aplicación.
Ejemplos de Uso
Ejemplos Prácticos
A continuación encontrarás ejemplos completos de cómo usar la API en diferentes lenguajes de programación. Estos ejemplos cubren los casos de uso más comunes.
Automatización de Servidores
Crea scripts para iniciar/detener servidores automáticamente según horarios o eventos.
Integración con Sistemas de Facturación
Conecta Aether Panel con sistemas como WHMCS, Blesta, o soluciones personalizadas para crear servidores automáticamente cuando un cliente realiza un pago.
Monitoreo y Alertas
Crea dashboards personalizados o integra con sistemas de monitoreo como Grafana, Prometheus, etc.
Backups Automáticos
Programa backups automáticos de tus servidores usando cron jobs o sistemas de scheduling.
Bots de Discord
Crea bots de Discord que permitan a los usuarios gestionar sus servidores desde Discord usando comandos.
Ejemplo con cURL
curl -X GET "https://aetherpanel.es/api/application/servers" \
-H "Authorization: Bearer <YOUR_API_KEY>" \
-H "Accept: Application/vnd.aether.v1+json"Python
pip install requestsimport requests
import json
class SkyPanelAPI:
def __init__(self, base_url, client_id, client_secret):
self.base_url = base_url
self.client_id = client_id
self.client_secret = client_secret
self.token = None
def authenticate(self):
"""Obtener token de acceso"""
url = f"{self.base_url}/oauth2/token"
data = {
'grant_type': 'client_credentials',
'client_id': self.client_id,
'client_secret': self.client_secret
}
response = requests.post(url, data=data)
response.raise_for_status()
self.token = response.json()['access_token']
return self.token
def get_headers(self):
"""Headers con autenticación"""
if not self.token:
self.authenticate()
return {
'Authorization': f'Bearer {self.token}',
'Content-Type': 'application/json'
}
def list_servers(self, **filters):
"""Listar servidores"""
url = f"{self.base_url}/api/servers"
response = requests.get(url, headers=self.get_headers(), params=filters)
response.raise_for_status()
return response.json()
def get_server(self, server_id):
"""Obtener servidor específico"""
url = f"{self.base_url}/api/servers/{server_id}"
response = requests.get(url, headers=self.get_headers())
response.raise_for_status()
return response.json()
def start_server(self, server_id):
"""Iniciar servidor"""
url = f"{self.base_url}/api/servers/{server_id}/start"
response = requests.post(url, headers=self.get_headers())
response.raise_for_status()
return True
def stop_server(self, server_id):
"""Detener servidor"""
url = f"{self.base_url}/api/servers/{server_id}/stop"
response = requests.post(url, headers=self.get_headers())
response.raise_for_status()
return True
def send_command(self, server_id, command):
"""Enviar comando a consola"""
url = f"{self.base_url}/api/servers/{server_id}/console"
data = {'command': command}
response = requests.post(url, headers=self.get_headers(), json=data)
response.raise_for_status()
return True
def create_server(self, server_data):
"""Crear servidor"""
server_id = server_data.get('identifier', '')
url = f"{self.base_url}/api/servers/{server_id}"
response = requests.put(url, headers=self.get_headers(), json=server_data)
response.raise_for_status()
return response.json()
# Uso
api = SkyPanelAPI(
base_url='http://localhost:8080',
client_id='YOUR_CLIENT_ID',
client_secret='YOUR_CLIENT_SECRET'
)
# Listar servidores
servers = api.list_servers(name='minecraft*')
print(f"Encontrados {len(servers['servers'])} servidores")
# Iniciar servidor
api.start_server('ABC12345')
print("Servidor iniciado")
# Enviar comando
api.send_command('ABC12345', 'say Hello from Python!')
print("Comando enviado")Node.js
npm install axiosconst axios = require('axios');
class SkyPanelAPI {
constructor(baseURL, clientId, clientSecret) {
this.baseURL = baseURL;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.token = null;
this.client = axios.create({
baseURL: this.baseURL
});
}
async authenticate() {
const response = await this.client.post('/oauth2/token',
new URLSearchParams({
grant_type: 'client_credentials',
client_id: this.clientId,
client_secret: this.clientSecret
}),
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
);
this.token = response.data.access_token;
return this.token;
}
getHeaders() {
if (!this.token) {
throw new Error('Not authenticated. Call authenticate() first.');
}
return {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json'
};
}
async listServers(filters = {}) {
const response = await this.client.get('/api/servers', {
headers: this.getHeaders(),
params: filters
});
return response.data;
}
async getServer(serverId) {
const response = await this.client.get(`/api/servers/${serverId}`, {
headers: this.getHeaders()
});
return response.data;
}
async startServer(serverId) {
await this.client.post(`/api/servers/${serverId}/start`, {}, {
headers: this.getHeaders()
});
return true;
}
async stopServer(serverId) {
await this.client.post(`/api/servers/${serverId}/stop`, {}, {
headers: this.getHeaders()
});
return true;
}
async sendCommand(serverId, command) {
await this.client.post(`/api/servers/${serverId}/console`,
{ command },
{ headers: this.getHeaders() }
);
return true;
}
async createServer(serverData) {
const serverId = serverData.identifier || '';
const response = await this.client.put(`/api/servers/${serverId}`,
serverData,
{ headers: this.getHeaders() }
);
return response.data;
}
}
// Uso
(async () => {
const api = new SkyPanelAPI(
'http://localhost:8080',
'YOUR_CLIENT_ID',
'YOUR_CLIENT_SECRET'
);
// Autenticar
await api.authenticate();
console.log('Autenticado');
// Listar servidores
const servers = await api.listServers({ name: 'minecraft*' });
console.log(`Encontrados ${servers.servers.length} servidores`);
// Iniciar servidor
await api.startServer('ABC12345');
console.log('Servidor iniciado');
// Enviar comando
await api.sendCommand('ABC12345', 'say Hello from Node.js!');
console.log('Comando enviado');
})();