Referencia de endpoints
Catálogo completo del API. Todas las rutas están bajo el prefijo https://www.rud1.es/api/v1/public.
Resumen
| Método | Ruta | Scope | Descripción |
|---|---|---|---|
| GET | /devices | devices:read | Listar dispositivos |
| GET | /devices/{id} | devices:read | Detalle de un dispositivo |
| GET | /devices/{id}/metrics | metrics:read | Series temporales de métricas |
| GET | /devices/{id}/events | logs:read | Eventos del dispositivo |
| GET | /devices/{id}/serial | devices:read | Estado y configuración de la E/S industrial |
| PATCH | /devices/{id}/serial | devices:write | Modo de uso y reenvío de señales |
| GET | /devices/{id}/serial/telemetry | devices:read | Últimas señales recibidas |
| GET | /devices/{id}/serial/channels/{channelId} | devices:read | Detalle de un canal |
| PUT | /devices/{id}/serial/channels/{channelId} | devices:write | Configurar un canal (incluye envío periódico) |
| GET | /alerts | alerts:read | Listar alertas |
| POST | /alerts/{id}/acknowledge | alerts:write | Reconocer una alerta |
| POST | /alerts/{id}/resolve | alerts:write | Resolver una alerta |
💡 Todas las respuestas incluyen los headers X-RateLimit-*. Las listas son cursor-paginadas: usa el campo nextCursor de la respuesta como valor de ?cursor=… para la siguiente página.
Dispositivos
GET /devices
Lista los dispositivos de la organización de la clave API.
| Parámetro | Tipo | Descripción |
|---|---|---|
| limit | 1..100 (default 25) | Tamaño de página |
| cursor | cuid | Cursor opaco para paginar |
| status | DeviceStatus | ONLINE / OFFLINE / CONNECTING / ERROR / PROVISIONING / REBOOTING / UPDATING |
GET /api/v1/public/devices?status=ONLINE&limit=10
Authorization: Bearer rud1_sk_...
200 OK
{
"data": [
{
"id": "clxxxxxxxxxxxxxxxxxxxxxxx",
"name": "PLC línea 3",
"serialNumber": "RUD1-000123",
"status": "ONLINE",
"model": "Rud1 Mini",
"firmwareVersion": "1.4.2",
"lastSeen": "2026-05-05T22:11:38.512Z",
"ipAddress": "192.168.1.42",
"location": "Planta 2 - Norte",
"createdAt": "2026-04-12T10:00:00.000Z"
}
],
"pagination": { "nextCursor": null, "hasMore": false }
}GET /devices/{id}
Devuelve el detalle de un dispositivo. Si el ID no pertenece a tu organización responde 404 not_found (no revelamos la existencia de recursos de otras organizaciones).
GET /api/v1/public/devices/clxxxxxxxxxxxxxxxxxxxxxxx
Authorization: Bearer rud1_sk_...
200 OK
{
"data": {
"id": "clxxxxxxxxxxxxxxxxxxxxxxx",
"name": "PLC línea 3",
"serialNumber": "RUD1-000123",
"status": "ONLINE",
"model": "Rud1 Mini",
"firmwareVersion": "1.4.2",
"lastSeen": "2026-05-05T22:11:38.512Z",
"ipAddress": "192.168.1.42",
"location": "Planta 2 - Norte",
"notes": null,
"agentDeviceName": "rud1-planta2",
"agentDeviceLocation": "Planta 2 - Norte",
"agentTimezone": "Europe/Madrid",
"createdAt": "2026-04-12T10:00:00.000Z"
}
}GET /devices/{id}/metrics
Series temporales de métricas de sistema (CPU, memoria, disco, temperatura, carga). El agente captura una muestra cada ~5 minutos.
| Parámetro | Tipo | Descripción |
|---|---|---|
| from | ISO 8601 | Inicio del rango (default: hace 1 hora) |
| to | ISO 8601 | Fin del rango (default: ahora) |
| limit | 1..1000 (default 200) | Máximo de muestras |
GET /api/v1/public/devices/clxx.../metrics?from=2026-05-05T20:00:00Z
Authorization: Bearer rud1_sk_...
200 OK
{
"data": [
{
"capturedAt": "2026-05-05T22:10:00.000Z",
"cpuPct": 18.4,
"memPct": 41.2,
"diskUsedPct": 32.8,
"tempCpu": 48.1,
"loadAvg1": 0.42
}
],
"window": {
"from": "2026-05-05T20:00:00.000Z",
"to": "2026-05-05T22:11:38.512Z"
}
}GET /devices/{id}/events
Stream de eventos del dispositivo: heartbeats, alertas que se abren y se resuelven, ciclo de vida del agente, USB, etc.
| Parámetro | Tipo | Descripción |
|---|---|---|
| limit | 1..200 (default 50) | Tamaño de página |
| cursor | cuid | Cursor de paginación |
| severity | string | Filtrar por INFO, WARNING, ERROR o CRITICAL |
| type | string | Filtrar por tipo (ej. 'alert.high_cpu') |
GET /api/v1/public/devices/clxx.../events?severity=ERROR&limit=10
Authorization: Bearer rud1_sk_...
200 OK
{
"data": [
{
"id": "clyyyyyyyyyyyyyyyyyyyyyyy",
"type": "alert.vpn_down",
"severity": "ERROR",
"message": "Secure tunnel 'wg0' is disconnected",
"data": {
"interfaceName": "wg0",
"endpoint": "203.0.113.1:51820",
"peerCount": 2
},
"createdAt": "2026-05-05T22:09:14.000Z"
}
],
"pagination": { "nextCursor": "clzzz...", "hasMore": true }
}E/S industrial (serial)
Configuración y lectura del puerto industrial: UART, RS485, CAN-FD y GPIO. Sólo responde en dispositivos cuyo modelo tenga la capability serial.io; si no, devuelve 409 capability_unavailable.
GET /devices/{id}/serial
Estado completo: modo de uso, reenvío, y cada canal del conector con su configuración y su último valor recibido.
GET /api/v1/public/devices/clxx.../serial
Authorization: Bearer rud1_sk_...
200 OK
{
"data": {
"deviceId": "clxxxxxxxxxxxxxxxxxxxxxxx",
"enabled": true,
"mode": "managed",
"forwarding": {
"webhookUrl": "https://tu-servidor/rud1/serial",
"webhookEnabled": true
},
"channels": [
{
"id": "rs485-0",
"group": "rs485",
"label": "RS485 · 1",
"terminals": ["a1", "b1"],
"configurable": true,
"available": true,
"config": {
"kind": "rs485",
"baudRate": 9600,
"dataBits": 8,
"parity": "none",
"stopBits": 1,
"mode": "modbus-rtu-master",
"slaveId": 1,
"tx": { "enabled": false, "intervalMs": 1000, "register": 0, "value": 1 }
},
"telemetry": { "live": "0x0012", "txOn": false, "error": "" }
}
],
"telemetryAt": "2026-05-05T22:11:38.512Z"
}
}PATCH /devices/{id}/serial
Cambia el modo de uso y/o el reenvío de señales. Envía al menos uno de mode, webhookUrl o webhookEnabled.
| Campo | Tipo | Descripción |
|---|---|---|
| mode | managed | passthrough | both | Gestionado desde el panel, expuesto en crudo por VPN, o ambos |
| webhookUrl | https URL | null | Destino del reenvío. null lo borra. Sin credenciales en la URL |
| webhookEnabled | boolean | Activa o pausa el reenvío |
PATCH /api/v1/public/devices/clxx.../serial
Authorization: Bearer rud1_sk_...
Content-Type: application/json
{ "mode": "managed", "webhookUrl": "https://tu-servidor/rud1/serial", "webhookEnabled": true }
200 OK
{
"data": {
"deviceId": "clxxxxxxxxxxxxxxxxxxxxxxx",
"mode": "managed",
"forwarding": {
"webhookUrl": "https://tu-servidor/rud1/serial",
"webhookEnabled": true
}
}
}PUT /devices/{id}/serial/channels/{channelId}
Configura un canal. El kind del cuerpo debe coincidir con el grupo del canal (400 kind_mismatch si no). El bloque tx es el envío de señales: con enabled: true el dispositivo transmite el valor cada intervalMs (0 = envío único).
PUT /api/v1/public/devices/clxx.../serial/channels/canfd-0
Authorization: Bearer rud1_sk_...
Content-Type: application/json
{
"kind": "canfd",
"nominalBitrate": 500000,
"dataBitrate": 2000000,
"samplePoint": 0.75,
"listenOnly": false,
"tx": { "enabled": true, "intervalMs": 1000, "canId": "100", "dataHex": "00 01" }
}
200 OK
{
"data": {
"deviceId": "clxxxxxxxxxxxxxxxxxxxxxxx",
"channelId": "canfd-0",
"config": { "kind": "canfd", "nominalBitrate": 500000, "...": "..." }
}
}GET /devices/{id}/serial/telemetry
Recepción de señales por sondeo: último valor que el dispositivo reportó en su heartbeat. at es null si aún no ha reportado ninguno.
GET /api/v1/public/devices/clxx.../serial/telemetry
Authorization: Bearer rud1_sk_...
200 OK
{
"data": {
"deviceId": "clxxxxxxxxxxxxxxxxxxxxxxx",
"at": "2026-05-05T22:11:38.512Z",
"channels": [
{ "id": "rs485-0", "live": "0x0012", "txOn": false, "error": "" },
{ "id": "canfd-0", "live": "100#0001", "txOn": true, "error": "" }
]
}
}Reenvío por webhook
Con el reenvío activo, cada heartbeat que traiga un cambio en una señal genera un POST a tu URL con los canales que cambiaron. Se reintenta con backoff hasta 5 veces y va firmado con X-Rud1-Signature (HMAC-SHA256 del cuerpo), igual que los webhooks de alertas.
POST https://tu-servidor/rud1/serial
X-Rud1-Signature: sha256=...
X-Rud1-Delivery-Id: cldddddddddddddddddddddd
X-Rud1-Attempt: 1
{
"event": "serial.signal",
"deviceId": "clxxxxxxxxxxxxxxxxxxxxxxx",
"at": "2026-05-05T22:11:38.512Z",
"channels": [
{ "id": "rs485-0", "live": "0x0012", "txOn": false, "error": "" }
]
}💡 Responde 2xx para confirmar la entrega. Cualquier 5xx, 408, 425 o 429 se reintenta; el resto se descarta sin reintento.
Alertas
GET /alerts
Lista las alertas de tu organización. Por defecto solo devuelve las que están en estado ACTIVE.
| Parámetro | Tipo | Descripción |
|---|---|---|
| state | ACTIVE | ACKNOWLEDGED | RESOLVED | Estado a filtrar (default ACTIVE) |
| severity | string | INFO / WARNING / ERROR / CRITICAL |
| deviceId | cuid | Filtrar por un dispositivo concreto |
| limit | 1..100 (default 25) | Tamaño de página |
| cursor | cuid | Cursor de paginación |
GET /api/v1/public/alerts?state=ACTIVE&severity=CRITICAL
Authorization: Bearer rud1_sk_...
200 OK
{
"data": [
{
"id": "claaaaaaaaaaaaaaaaaaaaaaa",
"state": "ACTIVE",
"severity": "CRITICAL",
"message": "CPU usage 96.4% exceeds 90%",
"payload": { "cpuUsage": 96.4, "threshold": 90 },
"deviceId": "clxxxxxxxxxxxxxxxxxxxxxxx",
"ruleId": "clrrrrrrrrrrrrrrrrrrrrrrrrr",
"acknowledgedAt": null,
"resolvedAt": null,
"createdAt": "2026-05-05T22:08:01.123Z"
}
],
"pagination": { "nextCursor": null, "hasMore": false }
}POST /alerts/{id}/acknowledge
Marca una alerta como reconocida. Idempotente: si ya está reconocida, devuelve la fila sin cambios. Si la alerta ya está RESOLVED responde 409 alert_already_resolved.
POST /api/v1/public/alerts/claaa.../acknowledge
Authorization: Bearer rud1_sk_...
200 OK
{
"data": {
"id": "claaaaaaaaaaaaaaaaaaaaaaa",
"state": "ACKNOWLEDGED",
"severity": "CRITICAL",
"message": "CPU usage 96.4% exceeds 90%",
"acknowledgedAt": "2026-05-05T22:12:00.000Z",
"resolvedAt": null,
"createdAt": "2026-05-05T22:08:01.123Z"
}
}POST /alerts/{id}/resolve
Marca la alerta como resuelta. Idempotente: si ya estaba resuelta no cambia el resolvedAt original — el timestamp se preserva como evidencia del primer cierre.
POST /api/v1/public/alerts/claaa.../resolve
Authorization: Bearer rud1_sk_...
200 OK
{
"data": {
"id": "claaaaaaaaaaaaaaaaaaaaaaa",
"state": "RESOLVED",
"severity": "CRITICAL",
"message": "CPU usage 96.4% exceeds 90%",
"acknowledgedAt": "2026-05-05T22:12:00.000Z",
"resolvedAt": "2026-05-05T22:14:33.000Z",
"createdAt": "2026-05-05T22:08:01.123Z"
}
}ℹ️ Reconocer ≠ resolver. ACKNOWLEDGED indica que alguien ha visto la alerta y está actuando sobre ella; RESOLVED indica que la condición se ha corregido. Una alerta puede pasar directamente de ACTIVE a RESOLVED sin pasar por ACKNOWLEDGED.