TMS · comandos y telemetría
El Merchant le ordena cosas a cada terminal desde la nube y sabe cómo está cada equipo por el latido que AuroraPOS manda cada 60 segundos. Lo mismo que ves en Flota del portal, disponible para tu software con X-API-Key bajo /api/v1/tms.
Tipos de comando
| Tipo | Payload | Qué hace el terminal |
|---|---|---|
ESTADO | — | Responde su telemetría inmediata en resultado (se registra como latido). |
PARAMETROS | — | Recarga sus parámetros del Merchant. |
ACTIVAR | — | Libera la pantalla. El servidor pone operationalState = ACTIVO al emitir. |
DESACTIVAR | {motivo?} | Bloquea la pantalla. El servidor pone SUSPENDIDO al emitir y rechaza autorizaciones (DE39 58), le llegue o no el comando a la app. |
ABRIR_APP | {pantalla?} | Trae AuroraPOS al frente. |
CERRAR_LOTE | — | El mismo cierre que el botón; devuelve totales en resultado. |
REINICIAR_APP | — | Reinicia la app (no el equipo). |
MENSAJE | {texto, titulo?} (texto ≤ 500) | Muestra el aviso al operador. |
COBRAR | {montoCentavos, moneda, referencia, descripcion?, pagador?} | Crea una intención VENTA y la empuja por el canal de órdenes (cobro empujado). |
REEMBOLSAR | igual que COBRAR | Crea una intención DEVOLUCION y la empuja. |
REEMBOLSAR, COBRAR y DESACTIVAR exigen solicitadoPor (o se toma la etiqueta de la clave) y quedan auditados con usuario e IP. ttlSegundos: 900 por defecto, máximo 86 400; para COBRAR/REEMBOLSAR rigen los del despacho (300, máximo 900).
Emitir un comando
curl -s -X POST https://pos.finoracore.com/api/v1/tms/terminales/TERM0042/comandos \
-H "X-API-Key: $FINORA_API_KEY" -H "Content-Type: application/json" \
-d '{"tipo":"MENSAJE","payload":{"texto":"Cierre de caja a las 18:00","titulo":"Aviso"},"ttlSegundos":600,"solicitadoPor":"supervisor.centro"}'
const comando = await fetch("https://pos.finoracore.com/api/v1/tms/terminales/TERM0042/comandos", {
method: "POST",
headers: { "Content-Type": "application/json", "X-API-Key": process.env.FINORA_API_KEY },
body: JSON.stringify({ tipo: "MENSAJE", payload: { texto: "Cierre de caja a las 18:00", titulo: "Aviso" }, ttlSegundos: 600, solicitadoPor: "supervisor.centro" }),
}).then((r) => r.json());
console.log(comando.id, comando.estado); // 41 PENDIENTE
var req = HttpRequest.newBuilder(URI.create("https://pos.finoracore.com/api/v1/tms/terminales/TERM0042/comandos"))
.header("Content-Type", "application/json").header("X-API-Key", System.getenv("FINORA_API_KEY"))
.POST(HttpRequest.BodyPublishers.ofString("{\"tipo\":\"MENSAJE\",\"payload\":{\"texto\":\"Cierre de caja a las 18:00\"},\"solicitadoPor\":\"supervisor.centro\"}"))
.build();
await http.PostAsJsonAsync("https://pos.finoracore.com/api/v1/tms/terminales/TERM0042/comandos",
new { tipo = "MENSAJE", payload = new { texto = "Cierre de caja a las 18:00", titulo = "Aviso" }, ttlSegundos = 600, solicitadoPor = "supervisor.centro" });
requests.post(f"https://pos.finoracore.com/api/v1/tms/terminales/TERM0042/comandos", headers={"X-API-Key": KEY},
json={"tipo": "MENSAJE", "payload": {"texto": "Cierre de caja a las 18:00"}, "ttlSegundos": 600, "solicitadoPor": "supervisor.centro"})
Respuesta 201 (ComandoDto):
{ "id": 41, "correlationId": "CMD-MENSAJE-60E99A19F8504F0FB763", "terminalId": "TERM0042", "tipo": "MENSAJE", "estado": "PENDIENTE",
"payload": { "texto": "Cierre de caja a las 18:00", "titulo": "Aviso" }, "solicitadoPor": "supervisor.centro", "solicitadoDesde": "203.0.113.5",
"intencionReferencia": null, "creadoEn": "…", "expiraEn": "…", "entregadoEn": null, "iniciadoEn": null, "terminadoEn": null,
"codigoResultado": null, "mensajeResultado": null, "resultado": {} }
Cobrar 2.499,00 VES en un motorizado (el comando espeja el despacho de la intención):
curl -s -X POST https://pos.finoracore.com/api/v1/tms/terminales/TERM0042/comandos -H "X-API-Key: $FINORA_API_KEY" -H "Content-Type: application/json" \
-d '{"tipo":"COBRAR","payload":{"montoCentavos":249900,"moneda":"VES","referencia":"PED-17","pagador":{"tipoDocumento":"V","documento":"12345678"}},"solicitadoPor":"erp"}'
montoCentavos es entero en la menor unidad de la moneda (2.499,00 → 249900). En el checkout y en /api/v1/pagos los importes van en unidades con decimales; en el TMS, en céntimos. Es a propósito: el comando viaja al terminal, que trabaja en enteros.
Ciclo de estados
PENDIENTE ──(sondeo)──▶ ENTREGADO ──(inicio)──▶ EJECUTANDO ──(resultado)──▶ OK | ERROR
│ cancelar (solo PENDIENTE) ──▶ CANCELADO └── vence expiresAt ──▶ EXPIRADO
Un solo comando en curso por terminal: los demás esperan en orden de creación. Para COBRAR/REEMBOLSAR: PENDIENTE→PENDIENTE, ENTREGADA→ENTREGADO, ACEPTADA→EJECUTANDO, COMPLETADA con 00→OK, otro código→ERROR, EN_DUDA→ERROR (resultCode = EN_DUDA), EXPIRADA→EXPIRADO, CANCELADA→CANCELADO.
Consultar
| Método | Ruta | Devuelve |
|---|---|---|
GET | /api/v1/tms/terminales/{tid}/comandos?estado=&desde=&max= | Historial, el más reciente primero (max ≤ 200). |
GET | /api/v1/tms/comandos/{id} | Un comando. |
POST | /api/v1/tms/comandos/{id}/cancelar | Solo PENDIENTE (409 TRANSICION_INVALIDA si ya se entregó). |
GET | /api/v1/tms/terminales/{tid}/estado | Telemetría + comandosAbiertos[] + ultimosLatidos[]. |
GET | /api/v1/tms/flota?merchantCode=COM00042 | {merchantCode, total, online, offline, terminales[]}. |
{ "terminalId": "TERM0042", "merchantCode": "COM00042", "storeCode": "SUC001", "checkoutType": "MOVIL",
"operationalState": "ACTIVO", "online": true, "ultimoLatido": "…", "appVersion": "1.10.2", "bateria": 63, "red": "WIFI", "sondeoCobros": "ACTIVO",
"ultimoCobro": "…", "serial": "SN-000123",
"comandosAbiertos": [], "ultimosLatidos": [ { "recibidoEn": "…", "bateria": 63, "cargando": true, "red": "WIFI", "senal": 90, "appVersion": "1.10.2", "sondeoCobros": "ACTIVO" } ] }
online = último latido hace menos de 3 minutos.
Estado operativo
operationalState: ACTIVO (por defecto), SUSPENDIDO (lo pones tú con DESACTIVAR) y BLOQUEADO (lo pone el adquirente: robo, fraude, sello violado; ningún comando lo toca). Un terminal que no está ACTIVO recibe 58 al autorizar aunque la app nunca haya recibido el comando: el control es del servidor.
Errores
codigo | HTTP | Cuándo |
|---|---|---|
PAYLOAD_INVALIDO | 400 | Tipo desconocido; MENSAJE sin texto; COBRAR sin montoCentavos entero > 0, moneda o referencia. |
COMANDO_NO_PERMITIDO | 403 | Comando sensible sin autor; ACTIVAR sobre BLOQUEADO; COBRAR a suspendido. |
COMANDO_NO_ENCONTRADO, TERMINAL_NO_ENCONTRADO | 404 | |
TRANSICION_INVALIDA | 409 | Cancelar lo ya entregado. |
TERMINAL_OCUPADO, DESPACHO_NO_PERMITIDO, ESTADO_INVALIDO | 409 / 403 | Los del despacho, para COBRAR/REEMBOLSAR. |
CLAVE_INVALIDA / CLAVE_SIN_ACCESO_AL_COMERCIO | 401 / 403 | X-API-Key. |