Saltar al contenido principal

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​

TipoPayloadQué 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).
REEMBOLSARigual que COBRARCrea 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
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"}'
Node.js
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
Java
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();
C#
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" });
Python
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"}'
nota

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étodoRutaDevuelve
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}/cancelarSolo PENDIENTE (409 TRANSICION_INVALIDA si ya se entregó).
GET/api/v1/tms/terminales/{tid}/estadoTelemetrí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​

codigoHTTPCuándo
PAYLOAD_INVALIDO400Tipo desconocido; MENSAJE sin texto; COBRAR sin montoCentavos entero > 0, moneda o referencia.
COMANDO_NO_PERMITIDO403Comando sensible sin autor; ACTIVAR sobre BLOQUEADO; COBRAR a suspendido.
COMANDO_NO_ENCONTRADO, TERMINAL_NO_ENCONTRADO404
TRANSICION_INVALIDA409Cancelar lo ya entregado.
TERMINAL_OCUPADO, DESPACHO_NO_PERMITIDO, ESTADO_INVALIDO409 / 403Los del despacho, para COBRAR/REEMBOLSAR.
CLAVE_INVALIDA / CLAVE_SIN_ACCESO_AL_COMERCIO401 / 403X-API-Key.