Descripción #
Cuando un móvil avanza un servicio desde la aplicación, AsistManager envía a la compañía una petición HTTP POST con el caso completo. Ese mensaje es el aviso de avance.
El cuerpo es siempre el mismo objeto, con todos los campos del caso. Nunca es una diferencia respecto del envío anterior: cada aviso es la fotografía entera del caso en ese momento.
La segunda mitad de este documento describe el otro mensaje que emite un móvil mientras trabaja: su posición. Los dos comparten la misma política de entrega y reintentos.
evento, event, tipo ni equivalente. El paso se deduce mirando qué campos Hora* dejaron de tener la fecha nula. Una integración que espere un discriminador explícito no va a encontrarlo: el discriminador son las fechas.null, ni como cadena vacía, ni con el campo ausente: llega con ese valor literal. Tratarlo como una fecha real produce demoras de más de cien años. La regla de lectura es simple: si el campo trae la fecha de 1899, ese paso no ocurrió.Cómo se deduce el paso #
| Paso | Campos que pasan a tener valor | <code>info.status</code> |
|---|---|---|
| Alta del caso | HoraInicio · UsuarioCarga | pendiente |
| Asignación a un móvil | HoraPasadoMovil · Movil · UsuarioAsignacion. En la primera asignación se completa además HoraActivacionInicial. | asignado |
| En camino | HoraEnCamino · UsuarioEnCamino | asignado, sin cambio |
| Arribo | HoraLlegada · UsuarioLlegada. Se completa también Patente, que el chofer confirma en el lugar. | arribado |
| Cierre | HoraFinal · TipoServicioFinal · UsuarioFinalizacion | finalizado |
| Bitácora | Observaciones · Historico | No cambia |
info.status sigue siendo asignado. No existe un estado en camino. La única manera de distinguir un móvil que ya salió de uno que todavía no es leer HoraEnCamino: si dejó de tener la fecha nula, el móvil está en camino. Quien muestre el estado al operador usando solo info.status va a perder ese paso.Envoltorio del mensaje #
{
"source": "<clave de la compañía>",
"identifier": "<id del caso, tal como lo creó la compañía>",
"alias": "<prestador que atiende>",
"date": "2026-09-17T11:42:08.310000-03:00",
"task": { … }
}
El envoltorio es invariable: estas cinco claves en todos los avisos de avance, sin importar el paso.
Campos del envoltorio #
| Campo | Tipo | Obligatorio | Valores posibles | Descripción |
|---|---|---|---|---|
source |
string | Obligatorio | — | La clave de la compañía de origen, la misma con la que se dio de alta el caso. |
identifier |
string | Obligatorio | — | El identificador del caso, tal como lo creó la compañía. Es la clave de correlación: es lo que permite saber a qué caso corresponde el aviso. |
alias |
string | Obligatorio | — | El prestador que está atendiendo el servicio. |
date |
string | Obligatorio | ISO 8601 con desplazamiento <code>-03:00</code> | Momento en que AsistManager emitió el aviso, en hora local. Sirve como reloj del emisor para ordenar mensajes que pudieron llegar desordenados. |
task |
objeto | Obligatorio | — | El caso completo, con todos sus campos. Está descripto en el documento de Consultas al prestador, en la sección El objeto task. Acá se detalla solo el bloque info, que es el que resume el avance. |
Ejemplo: aviso de arribo #
{
"source": "<clave de la compañía>",
"identifier": "20260917102415733",
"alias": "prestador",
"date": "2026-09-17T11:42:08.310000-03:00",
"task": {
"Numero": "20260917102415733",
"Empresa": "<clave de la compañía>",
"TipoServicioInicial": "Traslado",
"Movil": "movil-12",
"Patente": "AAA111",
"HoraInicio": "2026-09-17T13:24:15.733+00:00",
"HoraActivacionInicial": "2026-09-17T13:31:02.000+00:00",
"HoraPasadoMovil": "2026-09-17T13:31:02.000+00:00",
"HoraEnCamino": "2026-09-17T13:36:50.000+00:00",
"HoraLlegada": "2026-09-17T14:42:05.000+00:00",
"HoraFinal": "1899-12-30T00:00:00+00:00",
"TipoServicioFinal": "",
"UsuarioCarga": "USUARIOCARGA",
"UsuarioAsignacion": "USUARIOASIGNACION",
"UsuarioEnCamino": "USUARIOENCAMINO",
"UsuarioLlegada": "USUARIOLLEGADA",
"UsuarioFinalizacion": "",
"Observaciones": "Cia.ObsOrigen: \r\nCia.ObsDestino: \r\nCia.Obs:\r\nDemora: 45\r\nCia.Copago: \r\n",
"info": {
"status": "arribado",
"movil_id": "movil-12",
"servicio_realizado": null,
"servicio_final": null,
"demora_prometida": 45,
"demora_arribo": 77.82,
"demora_trabajo": 0,
"hora_inicio": "2026-09-17T13:24:15.733+00:00",
"hora_asignado": "2026-09-17T13:31:02.000+00:00",
"hora_arribo": "2026-09-17T14:42:05.000+00:00",
"hora_final": "1899-12-30T00:00:00+00:00"
}
}
}
El objeto task va completo: acá se muestran solo los campos que hacen falta para entender el ejemplo. Los datos son ficticios. Observe que HoraFinal todavía tiene la fecha nula y que HoraEnCamino ya tiene valor, aunque el estado había pasado por asignado sin reflejarlo.
El bloque info #
AsistManager agrega dentro de task un objeto info que resume el avance ya interpretado, para que la compañía no tenga que recalcularlo. Es un resumen, no un reemplazo: la fuente de verdad de los hitos siguen siendo los campos Hora*.
Campos de task.info #
| Campo | Tipo | Obligatorio | Valores posibles | Descripción |
|---|---|---|---|---|
status |
string | Obligatorio | <code>pendiente</code> · <code>asignado</code> · <code>arribado</code> · <code>finalizado</code> | Estado del caso. Son los cuatro únicos valores posibles. No hay un estado para «en camino». |
movil_id |
string | Obligatorio | — | Identificador del móvil asignado. Copia de Movil. |
servicio_realizado |
booleano | Obligatorio | — | Verdadero cuando el servicio se prestó. Es falso solamente si TipoServicioFinal es no reparo, cancelado con costo o cancelado sin costo. Llega en null antes del cierre, porque hasta entonces no hay respuesta posible. |
servicio_final |
string | Obligatorio | — | Copia de TipoServicioFinal. Llega en null antes del cierre. |
demora_prometida |
entero | Obligatorio | Minutos | Demora comprometida. Sale del campo Demora del caso o, si no está, de la línea Demora: N del bloque Observaciones. |
demora_arribo |
decimal | Obligatorio | Minutos | HoraLlegada menos HoraInicio, en minutos con decimales. Está limitada por abajo en cero: nunca llega negativa. |
demora_trabajo |
decimal | Obligatorio | Minutos | HoraFinal menos HoraLlegada, en minutos con decimales. También limitada por abajo en cero. |
hora_inicio · hora_asignado · hora_arribo · hora_final |
string | Obligatorio | — | Copias de los hitos correspondientes, para leerlos sin recorrer todo el caso. |
info incluye además alert, demora_transcurrida, porcentaje_transcurrido y demora_restante. Están reservados y hoy no transportan información: alert viaja siempre vacío y los otros tres siempre en cero. No los use para calcular ni para decidir. Si más adelante se activan, se documenta acá.Detalles de serialización #
Son particularidades del formato que conviene conocer antes de escribir el receptor, porque cada una rompió alguna integración alguna vez.
- Método y cuerpo
- El método es POST y el cuerpo es JSON. No hay firma del mensaje ni clave de idempotencia: el receptor no puede verificar el origen con el propio mensaje ni descartar repetidos por un identificador de envío.
- Codificación
- El cuerpo sale en ASCII con escapes
\uXXXX, no en UTF-8 directo. Un acento viaja como\u00e1. Cualquier analizador de JSON conforme lo resuelve solo; un tratamiento del cuerpo como texto plano, no. - Orden de las claves
- No está garantizado. No escriba lógica que dependa de la posición de un campo dentro del objeto.
- Denunciante y Titular
- Son campos distintos y pueden tener valores diferentes: quien llama no siempre es el titular del servicio.
- Color
- Puede llegar en
null. - Observaciones
- Usa
\r\ncomo separador de líneas y mezcla líneas con formatoClave: valorcon texto libre. Se analiza línea por línea, no con un formato fijo. - Campos Final*
- Los campos de precios llegan vacíos salvo que el prestador haya valorizado el servicio.
date del envoltorio viaja en -03:00 y los campos Hora* del caso, en +00:00. Conviven en el mismo cuerpo. Un analizador que asuma un único desplazamiento para todo el mensaje, o que recorte la zona horaria del texto, va a calcular mal las demoras. Convierta cada fecha respetando el desplazamiento que trae.Qué no dispara un aviso #
Hay avances reales del servicio que no producen un aviso. Conocerlos evita reportar como faltante algo que nunca se emitió.
| Situación | Comportamiento |
|---|---|
| El avance se carga desde los portales web | No se emite aviso. Solo notifica el avance registrado desde la aplicación del móvil. Un caso operado enteramente desde el escritorio no genera ningún aviso, aunque el estado del caso cambie. |
El identificador del caso contiene manual | No se emite aviso. Son casos de carga manual. |
El identificador del caso empieza con DEMO- | No se emite aviso. Son casos de demostración. |
Entrega y reintentos #
La entrega se considera exitosa cuando el receptor responde con un código HTTP 2xx. Cualquier otra respuesta, y también la falta de respuesta, se consideran error y habilitan el reintento.
Esta política es común a los avisos de avance, a los adjuntos, a las respuestas de consulta y a las posiciones. Lo que cambia entre ellos es cuánto tiempo se insiste.
Cadencia de reintentos #
| Tramo | Intentos | Intervalo |
|---|---|---|
| Primer envío | 1 | Inmediato |
| Tramo 1 | 10 | Cada 30 segundos |
| Tramo 2 | 10 | Cada 60 segundos |
| Tramo 3 | 6 | Cada 5 minutos |
| Después | Hasta que caduque | Cada 5 minutos |
Caducidad por tipo de mensaje #
| Mensaje | Caduca a los |
|---|---|
| Aviso de avance de caso | 5 días desde que se generó |
| Adjunto | 5 días desde que se generó |
| Respuesta a una consulta | 15 minutos |
| Posición de un móvil | 15 minutos |
Hora* recibidos contra los que ya se conocen y descartar el mensaje si no aportan un hito nuevo, y usar date como reloj del emisor para no aplicar un mensaje anterior al último aplicado.Coordenadas del móvil ocupado #
Mientras un móvil atiende un servicio de la compañía, AsistManager le reenvía las posiciones que el teléfono del chofer reporta. Es un mensaje distinto del aviso de avance y tiene su propio envoltorio.
El objetivo es que la compañía pueda mostrar el móvil en su mapa y estimar el arribo con datos propios, sin pedirle nada al prestador.
Condiciones para que una posición se envíe #
-
1
Pasaron al menos 30 segundosDesde la posición anterior de ese mismo móvil. Las posiciones más frecuentes que ese intervalo no se reenvían.
-
2
Hay un caso activo de esa compañía con ese móvilAsignado dentro de las últimas 24 horas. Sin un caso que lo justifique, no hay envío.
-
3
El identificador del caso no contiene <code>manual</code>Los casos de carga manual no producen reenvío de posiciones, igual que no producen avisos de avance.
Envoltorio de una posición #
{
"fecha": "2026-09-17T11:44:12.000000-03:00",
"data": { … }
}
fecha es la hora local del reenvío. El objeto data es la medición del dispositivo, tal como la reportó el teléfono.
Ejemplo de posición #
{
"fecha": "2026-09-17T11:44:12.000000-03:00",
"data": {
"worker": "movil-12",
"lat": -34.5401234,
"lng": -58.4802345,
"accuracy": 8.4,
"timestamp": "2026-09-17T14:44:09.000Z",
"local_timestamp": "2026-09-17T11:44:09.000-03:00",
"speed": 11.2,
"heading": 274.5,
"altitude": 23.0,
"battery": 0.62,
"is_moving": true,
"activity": "in_vehicle",
"last_position": { … },
"calculated": {
"lat": "-34.5401234",
"lng": "-58.4802345",
"percent": "0.4000000",
"lat_offset_1sec": "0.0000090",
"lng_offset_1sec": "-0.0001080"
},
"address": { … },
"prediction": {
"model": "curve",
"speed_mps": 11.2,
"samples": 6,
"confidence": 0.82,
"heading": 274.5,
"turn_rate_deg_s": -3.4,
"radius_m": 188.6
},
"info": { … }
}
}
Coordenadas y valores de ejemplo, no corresponden a un servicio real.
Campos de la medición #
| Campo | Tipo | Obligatorio | Valores posibles | Descripción |
|---|---|---|---|---|
worker |
string | Obligatorio | — | Identificador del móvil. Es el mismo valor que llega en Movil y en info.movil_id del aviso de avance, y es lo que permite asociar la posición con el caso. |
lat · lng |
decimal | Obligatorio | Grados decimales | Posición reportada por el dispositivo. |
accuracy |
decimal | Obligatorio | Metros | Precisión estimada de la medición. Un valor alto indica una posición poco confiable, típica de un túnel o de un estacionamiento cubierto. |
timestamp |
string | Obligatorio | ISO 8601 en UTC | Momento de la medición en el dispositivo. |
local_timestamp |
string | Obligatorio | — | El mismo momento expresado en la hora local del dispositivo. |
speed |
decimal | Opcional | Metros por segundo · <code>-1</code> | Velocidad instantánea. El valor -1 significa que se desconoce, no que el móvil esté detenido. |
heading |
decimal | Opcional | Grados · <code>-1</code> | Rumbo. El valor -1 significa que se desconoce. |
altitude |
decimal | Opcional | Metros | Altitud reportada por el dispositivo. |
battery |
decimal | Opcional | De 0 a 1 | Carga de la batería del teléfono, como fracción. 0.62 es 62 por ciento. |
is_moving |
booleano | Opcional | — | Indica si el dispositivo se considera en movimiento. |
activity |
string | Opcional | <code>still</code> · <code>in_vehicle</code> y otros valores propios del sistema operativo | Actividad detectada por el sistema operativo del teléfono. El conjunto de valores lo define el sistema operativo, no AsistManager, de modo que conviene tratar un valor desconocido como sin información en lugar de rechazarlo. |
last_position |
objeto | Opcional | — | La posición anterior del mismo móvil. Permite calcular un desplazamiento sin guardar estado del lado del receptor. |
calculated |
objeto | Opcional | — | Valores auxiliares para extrapolar la posición entre dos refrescos. Se detallan más abajo. |
address |
objeto | Opcional | — | La dirección resuelta por el servicio de mapas propio: calle, altura, calle transversal, distancia a la esquina y la cadena administrativa completa de la ubicación. |
prediction |
objeto | Opcional | — | Predicción de movimiento calculada en el teléfono. No siempre está presente. Se detalla más abajo. |
info |
objeto | Opcional | — | Datos del móvil que reporta: el nombre del chofer y la organización a la que pertenece. |
El bloque calculated #
| Campo | Tipo | Obligatorio | Valores posibles | Descripción |
|---|---|---|---|---|
lat · lng |
string | Obligatorio | Grados decimales con 7 decimales | Posición calculada sobre la que se aplican los desplazamientos. |
percent |
string | Obligatorio | — | Avance relativo entre la posición anterior y la actual. |
lat_offset_1sec · lng_offset_1sec |
string | Obligatorio | Grados por segundo | Cuánto se desplaza el móvil en un segundo, en cada eje. Sumándolos a la posición se anima el avance entre dos refrescos sin esperar la medición siguiente. |
Los cinco valores llegan como cadenas de texto con siete decimales, no como números. Hay que convertirlos antes de operar con ellos.
La predicción de movimiento #
El bloque prediction describe cómo se está moviendo el móvil, para poder animarlo entre dos refrescos siguiendo el arco real de la calle en lugar de una recta entre dos puntos. En una curva, la diferencia entre ambas representaciones es visible: el ícono deja de cortar por la vereda.
Se calcula en el teléfono, sobre las últimas seis posiciones, con dos umbrales: se considera que el móvil está quieto por debajo de 1,5 metros por segundo, y que está en curva cuando el giro sostenido supera 1,5 grados por segundo de forma consistente.
prediction: tiene que funcionar sin él y usarlo como mejora cuando llega. La proporción va a crecer con la actualización del parque de teléfonos, pero no hay una fecha a partir de la cual esté garantizado.Campos de prediction #
| Campo | Tipo | Obligatorio | Valores posibles | Descripción |
|---|---|---|---|---|
model |
string | Obligatorio | <code>still</code> · <code>linear</code> · <code>curve</code> | Modelo de movimiento detectado. Los tres valores son esos exactos, en inglés y en minúsculas. |
speed_mps |
decimal | Obligatorio | Metros por segundo | Velocidad estimada sobre la ventana de posiciones usada. |
samples |
entero | Obligatorio | Hasta 6 | Cuántas posiciones se usaron para el cálculo. Un valor bajo indica una estimación recién iniciada. |
confidence |
decimal | Obligatorio | De 0 a 1 | Confianza del modelo. Conviene fijar un umbral propio por debajo del cual se ignora la predicción y se anima en línea recta. |
heading |
decimal | Condicional Cuando el modelo lo determina | Grados | Rumbo estimado por la predicción. |
turn_rate_deg_s |
decimal | Condicional Cuando el modelo lo determina | Grados por segundo, con signo | Velocidad de giro. El signo indica el sentido del giro. |
radius_m |
decimal | Condicional
Solo con model igual a curve
|
Metros | Radio del arco que describe el móvil. |
Los tres modelos #
| <code>model</code> | Qué significa | Cómo conviene representarlo |
|---|---|---|
still | El móvil está quieto: la velocidad está por debajo de 1,5 metros por segundo. | No animar. Mantener el ícono en su lugar evita el temblor por error de medición. |
linear | El móvil avanza en línea recta. | Interpolar entre la posición actual y la proyección del rumbo. |
curve | El móvil describe un arco: el giro sostenido supera 1,5 grados por segundo. | Animar sobre el arco usando radius_m y turn_rate_deg_s. |
activity es la actividad que reconoce el sistema operativo del teléfono, con su propia lógica y su propia inercia; prediction.model es geometría calculada sobre las últimas seis posiciones. Un móvil detenido en un semáforo puede reportar in_vehicle y still al mismo tiempo, y eso no es un error. Si tiene que elegir uno para mover el ícono en el mapa, use prediction.model; activity describe al chofer, no al desplazamiento.info de la medición trae el nombre del chofer y la organización a la que pertenece. Lo decimos de forma explícita para que la compañía sepa qué dato está recibiendo y lo trate en consecuencia dentro de su propio sistema.Errores frecuentes #
La mayoría de los reclamos de integración sobre este mensaje se explican por alguno de estos puntos.
| Código | Qué se ve | Causa | Cómo se resuelve |
|---|---|---|---|
Sin avisos |
El caso avanza y la compañía no recibe nada | El avance se está cargando desde los portales web, o el identificador contiene manual o empieza con DEMO-. |
Verificar por qué vía se está operando el caso. Solo el avance registrado desde la aplicación del móvil genera aviso. |
Estado que retrocede |
Un caso finalizado vuelve a verse como asignado | Se aplicó un aviso viejo, llegado tarde o repetido, encima de uno más nuevo. El cuerpo es el caso completo, así que sobrescribe. | Descartar el mensaje si no aporta un hito Hora* nuevo, o comparar date contra el del último mensaje aplicado. |
Se pierde «en camino» |
El operador nunca ve que el móvil salió | Se está leyendo solo info.status, que sigue en asignado durante ese paso. |
Leer HoraEnCamino: si dejó de tener la fecha nula, el móvil salió. |
Demoras absurdas |
Aparecen tiempos de más de cien años | Se tomó la fecha nula 1899-12-30T00:00:00+00:00 como una fecha real. |
Tratar ese valor como el paso no ocurrió antes de cualquier cálculo. |
Demoras corridas 3 horas |
Los tiempos calculados no coinciden con la operación | Se asumió un único desplazamiento horario para todo el mensaje. date viaja en -03:00 y los Hora* en +00:00. |
Analizar cada fecha con el desplazamiento que trae, sin recortarlo ni normalizarlo a mano. |
Mensajes perdidos |
Después de una caída propia faltan avisos que nunca se recuperan | El receptor respondió 4xx durante la caída. Con dos respuestas 4xx que no sean 408 ni 429, el mensaje se descarta. | Responder 5xx ante una falla temporal. Con 5xx se reintenta durante cinco días. |
Sin posiciones |
No llegan coordenadas de un móvil | El móvil no tiene un caso activo de esa compañía asignado en las últimas 24 horas, o no pasaron 30 segundos desde su posición anterior. | Es el comportamiento esperado. Un móvil libre no reporta su posición a ninguna compañía. |
Animación entrecortada |
El ícono del móvil salta en lugar de moverse | Se está esperando prediction, que solo envía una minoría de los móviles. |
Usar calculated como base de la animación y prediction como mejora cuando está presente. |
Compatibilidad #
| Componente | Desde | Estado | Nota |
|---|---|---|---|
| Aviso de avance con el caso completo | En producción |
vigente | Uso masivo. El formato del envoltorio no cambió. |
| Bloque <code>task.info</code> | En producción |
vigente | Resumen del avance ya interpretado. |
| <code>alert</code> · <code>demora_transcurrida</code> · <code>porcentaje_transcurrido</code> · <code>demora_restante</code> | Reservados |
Planificado | Presentes en el mensaje, sin información: alert vacío y los otros tres en cero. |
| Reenvío de posiciones del móvil ocupado | En producción |
vigente | Sujeto a las tres condiciones de envío. |
| Bloque <code>prediction</code> | Según la versión de la aplicación |
vigente | Opcional. Hoy lo envía una minoría de los móviles. No se puede depender de él. |