Novedad: el cortafuegos de IA supervisa cada módulo y explica cada incidente con palabras sencillas. Vea cómo funciona

API de comandos

Envía comandos a los dispositivos, espera o consulta sus resultados, cancélalos y gestiona el catálogo de comandos de un perfil mediante REST: campos, estados, límites y errores.

Un comando (un RPC) pide a un dispositivo que haga algo y, salvo que sea unidireccional, espera la respuesta del dispositivo. Cada comando se guarda como una solicitud con un estado, para que puedas enviarlo ahora y leer el resultado más tarde. Cómo funcionan los comandos para las personas en la aplicación se explica en Envío de comandos a dispositivos. Las rutas están bajo https://<your host>/tenant/<tenantId>.

En desarrollo: Los comandos a dispositivos detrás de una pasarela (los dispositivos hijos de una pasarela) están en desarrollo. Envía comandos a dispositivos que se conectan por sí mismos.

Rutas

MétodoRutaPermisoFunción
POST/api/iot/devices/{deviceId}/rpciot_rpc.read más el nivel del comandoEnviar un comando
GET/api/iot/devices/{deviceId}/rpciot_rpc.readEl historial de comandos del dispositivo
GET/api/iot/rpc/{rpcId}iot_rpc.readUn comando con su respuesta
POST/api/iot/rpc/{rpcId}/canceliot_rpc.read más el nivel del comandoCancelar un comando en cola o enviado
GET/api/iot/devices/{deviceId}/rpc-commandsiot_rpc.send.basicLos comandos que un control del panel puede enviar a este dispositivo
GET/api/iot/rpc-commands/{profileId}iot_rpc.readEl catálogo de comandos de un perfil (?format=export para el formato de importación)
POST/api/iot/rpc-commands/{profileId}iot_rpc.commands.manageAñadir un comando al catálogo
PUT/api/iot/rpc-commands/{profileId}iot_rpc.commands.manageReemplazar todo el catálogo
PATCH, DELETE/api/iot/rpc-commands/{profileId}/{commandId}iot_rpc.commands.manageCambiar o eliminar un comando

Quién puede enviar qué

Cada comando del catálogo de un perfil tiene un nivel. El nivel determina el permiso:

NivelPermisoRol predeterminado¿Puede tenerlo una clave de API?
basiciot_rpc.send.basicUsuarioSí
privilegediot_rpc.send.privilegedAdministradorSí
criticaliot_rpc.send.criticalAdministradorSí
raw (un método que no está en el catálogo)iot_rpc.send.rawPropietarioNo

Así, una clave de API solo puede enviar métodos que estén en el catálogo del perfil del dispositivo.

Enviar un comando

POST/tenant/{tenantId}/api/iot/devices/{deviceId}/rpc

Campos: method (obligatorio, namespace.verb, hasta 64 caracteres), params (cualquier JSON, como máximo 16 KiB), oneway, persistent, timeoutMs (de 1.000 a 600.000; por defecto el del catálogo o el del perfil, si no 10.000), expiresInS (de 1 a 604.800, para un comando persistente; por defecto 86.400), wait, confirm, confirmText, source (api, console o dashboard_control). Un comando bidireccional, no persistente, con un tiempo de espera de como máximo 30 segundos espera a su final y responde 200; cualquier otro caso responde 202 y continúa en segundo plano.

Cuerpo de la solicitud application/json

{
    "method": "pump.start",
    "params": {
        "speed": 80
    },
    "timeoutMs": 15000
}

Ejemplo curl

curl -X POST 'https://<your-host>/tenant/{tenantId}/api/iot/devices/{deviceId}/rpc' \
  -H 'Content-Type: application/json' \
  -d '{"method":"pump.start","params":{"speed":80},"timeoutMs":15000}'

Respuestas

200OK
{
    "rpc": {
        "rpcId": "c0de…",
        "deviceId": "6f1c…",
        "method": "pump.start",
        "status": "SUCCESSFUL",
        "outcome": null,
        "response": {
            "ok": true
        },
        "error": null,
        "tier": "privileged",
        "highImpact": false,
        "source": "api",
        "createdAt": "2026-11-09T09:00:00.000Z",
        "completedAt": "2026-11-09T09:00:01.200Z",
        "…": "…"
    }
}
202Accepted
{
    "rpc": {
        "rpcId": "c0de…",
        "status": "QUEUED",
        "…": "…"
    }
}
403Forbidden
{
    "message": "You are not permitted to perform this action",
    "code": "FORBIDDEN"
}
409Conflict
{
    "message": "The device is disabled or quarantined; it takes no commands.",
    "code": "CONFLICT",
    "details": {
        "reason": "device_not_active"
    }
}
429Too Many Requests
{
    "message": "Too many commands to this device; try again in a minute.",
    "code": "RATE_LIMIT_EXCEEDED",
    "details": {
        "reason": "device_rate_limited"
    }
}
  • Unidireccional (oneway: true): el comando se completa correctamente cuando se entrega; no se espera respuesta.
  • Persistente (persistent: true): si el dispositivo está desconectado, el comando espera a que se conecte durante un máximo de expiresInS y después termina en EXPIRED.
  • wait: true fuerza la espera (se rechaza con «A synchronous call waits at most 30 s; use wait: false for a longer timeout.» cuando el comando no puede terminar en 30 s); false responde siempre 202 de inmediato.
  • Comandos de alto impacto necesitan "confirm": true y la frase escrita en confirmText cuando el comando del catálogo la tiene. Sin ello: «This command needs confirm: true.» Se registran en el registro de auditoría al enviarse y al terminar, y se envían como máximo una vez.

No hay clave de idempotencia en esta ruta: cada POST crea un nuevo comando. Si tu llamada agota el tiempo de espera en la red, consulta el historial del dispositivo antes de volver a enviar.

Estados

QUEUED → SENT → DELIVERED → SUCCESSFUL, o uno de FAILED, TIMEOUT, EXPIRED, CANCELLED.

EstadoSignificado
SUCCESSFULLlegó la respuesta, o un comando unidireccional fue entregado
FAILEDEl dispositivo lo rechazó, o no pudo enviarse
TIMEOUTNo hubo respuesta a tiempo. El resultado es desconocido: el dispositivo pudo haberlo ejecutado. outcome es unknown.
EXPIREDNunca llegó al dispositivo antes de su caducidad
CANCELLEDCancelado mientras estaba en cola o enviado

outcome añade detalle: running (el dispositivo aceptó un comando de larga duración), unknown (un tiempo de espera agotado) o late (una respuesta llegó después del final). Los resultados se conservan 90 días por defecto.

Leer resultados

Consulta GET /api/iot/rpc/{rpcId} hasta que el estado sea final, o suscríbete a los eventos de webhook rpc.completed y rpc.failed y lee la respuesta cuando llegue. Consulta la Referencia de eventos de webhook.

Historial de un dispositivo, del más reciente al más antiguo:

GET /api/iot/devices/{deviceId}/rpc?status=FAILED&limit=50

Sin page, el historial se lee con un cursor: status, method, from, to (fechas), limit (de 1 a 100, por defecto 25) y cursor. La respuesta es { "requests": [...], "nextCursor": "…" }; pasa nextCursor de vuelta como cursor hasta que sea null. Con page (desde 0), la lista sigue las reglas habituales de listas: pageSize, search, sort (method, status, source, createdAt, completedAt), status y source como listas separadas por comas, createdFrom, createdTo; la respuesta es { "requests": [...], "total": n }. Los parámetros secretos se enmascaran en todas las respuestas.

Cancelar

POST /api/iot/rpc/{rpcId}/cancel pasa un comando QUEUED o SENT a CANCELLED y responde { "rpc": {...} }. Otros estados: 409 «Only a queued or sent request can be cancelled.» Cancelar necesita el mismo permiso de nivel que enviar. Una cancelación no envía webhook.

Límites

LímitePredeterminado
Comandos por dispositivo10 por minuto (429, Retry-After: 60)
Comandos por organización600 por minuto (429 «Too many requests for your plan. Please upgrade or try again later.»)
Parámetros16 KiB de JSON
Respuesta conservada64 KiB
Comandos por catálogo de perfil200

Rechazos

Estadodetails.reasonMensaje
400bad_paramsLos parámetros no coinciden con el comando.
400wait_too_longUna llamada síncrona espera como máximo 30 s; usa wait: false para un tiempo de espera mayor.
400confirm_required, confirm_text_mismatchThis command needs confirm: true. / The typed confirmation does not match.
400method_refusedEl restablecimiento de fábrica, el emparejamiento, el olvido de Wi-Fi y el olvido de la nube nunca se envían desde la nube.
400payload_too_largeLa solicitud es mayor de lo que acepta el dispositivo.
403rpc_method_reservedEl método pertenece a un módulo propio (por ejemplo, el acceso remoto) y solo lo envía ese módulo; details.owner indica el módulo.
404Dispositivo no encontrado.
409rpc_not_supported_by_profileEl perfil del dispositivo solo usa los temas Legacy, que no transportan RPC.
409device_not_activeEl dispositivo está deshabilitado o en cuarentena.
409not_cancellableSolo se puede cancelar una solicitud que esté en cola o enviada.
429device_rate_limitedDemasiados comandos para este dispositivo; inténtalo de nuevo en un minuto.

El catálogo de comandos

Un comando del catálogo tiene: method, label (hasta 120), description, paramsSchema (hasta 50 campos, cada uno con label, type de text, textarea, number, boolean, select, multi-select o json, y opcionalmente required, min, max, step, options), maskedParams (campos secretos que nunca se muestran de nuevo), tier (basic, privileged, critical), highImpact, oneway, long, defaultTimeoutMs, persistentDefault, confirmText (solo para alto impacto).

{
  "method": "valve.set",
  "label": "Set valve position",
  "tier": "privileged",
  "paramsSchema": { "position": { "label": "Position (%)", "type": "number", "min": 0, "max": 100, "required": true } }
}

GET ...?format=export devuelve { "commands": [...] } sin ids, que PUT acepta de nuevo para copiar un catálogo a otro perfil.