API de silencios de alertas (omisiones)

versión 1.0.0 · OpenAPI 3.0.3
URL basehttps://apiomi.silencio.quro.com.mx
FormatoJSON · fechas en UTC (ISO 8601)
Contrato para herramientas/openapi.json (Postman, Swagger, Insomnia)

Silencia una alerta para un vehículo durante N horas: mientras dure, el motor de omisiones NO la notifica a ese vehículo.

Cómo implementarlo, en 4 pasos

  1. Silenciar: POST /api/alertas/silenciar con alerta_id, vehiculo_id, uid_empresa y horas. Guarda el _id que regresa.
  2. Mostrar lo silenciado: GET /api/alertas/silenciadas?uid_empresa=…&activas=true (paginado) o GET /api/alertas/silenciadas/vehiculo/{vehiculo_id}. Usa restante_segundos para el contador.
  3. Reanudar antes de tiempo: DELETE /api/alertas/silenciar/{_id} o, si sólo tienes los dos IDs, DELETE /api/alertas/silenciar?alerta_id=…&vehiculo_id=….
  4. Auditoría: manda siempre creado_por / cancelado_por con { uid, nombre, email } del usuario que lo hizo.

Errores: todas las respuestas de error traen { "error": "texto" } salvo el 403 (lo contesta el nginx por un Origin no permitido).

POST /api/alertas/silenciar

Silenciar una alerta para un vehículo

Crea el silencio, o REINICIA su duración si ya había uno activo para ese par alerta + vehículo.

Cuerpo (JSON)

CampoObligatorioTipoQué es
alerta_idsístring

ObjectId de la alerta (configuración) a silenciar.

vehiculo_idsístring

ObjectId del vehículo o su UID_Externo (el que usa el panel).

uid_empresasístring

ObjectId (24 hex) de la empresa dueña del vehículo en la base de omisiones. No es el UUID de la empresa en GPS.

horassínumber (máx. 720)

Duración en horas (máximo 720).

motivonostring (hasta 200 car.)

Opcional, hasta 200 caracteres.

creado_pornoobject

Quién hizo la acción (auditoría). Opcional. También se acepta un texto plano, o los campos planos <accion>_uid, <accion>_nombre y <accion>_email.

Ejemplo de cuerpo
{
  "alerta_id": "69eb9d55a1b2c3d4e5f60718",
  "vehiculo_id": "69c56400a1b2c3d4e5f60006",
  "uid_empresa": "66f1a2b3c4d5e6f708192a3b",
  "horas": 12,
  "motivo": "Unidad en taller",
  "creado_por": {
    "uid": "0d8f1c2e-6b8a-4c7e-9a51-2f3e4d5c6b7a",
    "nombre": "Ana López",
    "email": "ana.lopez@empresa.com"
  }
}

Respuestas

201

Silencio creado o renovado.

Ejemplo
{
  "ok": true,
  "silencio": {
    "_id": "670d5f1a2b3c4d5e6f708192",
    "uid_empresa": "66f1a2b3c4d5e6f708192a3b",
    "alerta_id": "69eb9d55a1b2c3d4e5f60718",
    "alerta_nombre": "DETENCIÓN DE UNIDAD",
    "vehiculo_id": "69c56400a1b2c3d4e5f60006",
    "vehiculo_alias": "TR-685",
    "vehiculo_uid_externo": null,
    "silenciada_desde": "2026-10-14T20:00:00.000Z",
    "silenciada_hasta": "2026-10-15T08:00:00.000Z",
    "horas": 12,
    "motivo": "Unidad en taller",
    "creado_por": {
      "uid": "0d8f1c2e-6b8a-4c7e-9a51-2f3e4d5c6b7a",
      "nombre": "Ana López",
      "email": "ana.lopez@empresa.com"
    },
    "creado_en": "2026-10-14T20:00:00.000Z",
    "cancelado_por": null,
    "cancelado_en": null,
    "expirado_en": null,
    "status": 1,
    "restante_segundos": 43200
  }
}
400

Faltan campos o valores inválidos.

Ejemplo
{
  "error": "horas excede el máximo permitido (720)"
}
403

La petición no viene de un sitio https://*.quro.com.mx (cabecera Origin). Lo contesta el nginx, sin cuerpo JSON.

404

El vehículo no existe (por UID_Externo).

Ejemplo
{
  "error": "Vehículo no encontrado por UID_Externo: b1c2d3e4-…"
}
500

Error inesperado del servicio.

Ejemplo
{
  "error": "Error desconocido"
}
Ejemplo con curl
curl -X POST 'https://apiomi.silencio.quro.com.mx/api/alertas/silenciar' \
  -H 'Origin: https://tu-app.quro.com.mx' \
  -H 'Content-Type: application/json' \
  -d '{"alerta_id":"69eb9d55a1b2c3d4e5f60718","vehiculo_id":"69c56400a1b2c3d4e5f60006","uid_empresa":"66f1a2b3c4d5e6f708192a3b","horas":12,"motivo":"Unidad en taller","creado_por":{"uid":"0d8f1c2e-6b8a-4c7e-9a51-2f3e4d5c6b7a","nombre":"Ana López","email":"ana.lopez@empresa.com"}}'

Fuera de un navegador hay que mandar Origin de un sitio *.quro.com.mx; el navegador lo pone solo.

Ejemplo desde la app web (fetch)
const r = await fetch('https://apiomi.silencio.quro.com.mx/api/alertas/silenciar', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    "alerta_id": "69eb9d55a1b2c3d4e5f60718",
    "vehiculo_id": "69c56400a1b2c3d4e5f60006",
    "uid_empresa": "66f1a2b3c4d5e6f708192a3b",
    "horas": 12,
    "motivo": "Unidad en taller",
    "creado_por": {
      "uid": "0d8f1c2e-6b8a-4c7e-9a51-2f3e4d5c6b7a",
      "nombre": "Ana López",
      "email": "ana.lopez@empresa.com"
    }
  }),
});
const datos = await r.json();   // { ok: true, ... } o { error: '...' }

DELETE /api/alertas/silenciar

Cancelar el silencio activo de un par alerta + vehículo

Para cuando la pantalla tiene los dos IDs pero no el _id del silencio.

Parámetros

NombreDóndeObligatorioTipoQué es
alerta_idquerysístring
vehiculo_idquerysístring

ObjectId o UID_Externo.

Cuerpo (JSON)

CampoObligatorioTipoQué es
cancelado_pornoobject

Quién hizo la acción (auditoría). Opcional. También se acepta un texto plano, o los campos planos <accion>_uid, <accion>_nombre y <accion>_email.

Respuestas

200

Silencio cancelado (status 0).

Ejemplo
{
  "ok": true,
  "silencio": {
    "_id": "670d5f1a2b3c4d5e6f708192",
    "uid_empresa": "66f1a2b3c4d5e6f708192a3b",
    "alerta_id": "69eb9d55a1b2c3d4e5f60718",
    "alerta_nombre": "DETENCIÓN DE UNIDAD",
    "vehiculo_id": "69c56400a1b2c3d4e5f60006",
    "vehiculo_alias": "TR-685",
    "vehiculo_uid_externo": null,
    "silenciada_desde": "2026-10-14T20:00:00.000Z",
    "silenciada_hasta": "2026-10-15T08:00:00.000Z",
    "horas": 12,
    "motivo": "Unidad en taller",
    "creado_por": {
      "uid": "0d8f1c2e-6b8a-4c7e-9a51-2f3e4d5c6b7a",
      "nombre": "Ana López",
      "email": "ana.lopez@empresa.com"
    },
    "creado_en": "2026-10-14T20:00:00.000Z",
    "cancelado_por": null,
    "cancelado_en": "2026-10-14T22:00:00.000Z",
    "expirado_en": null,
    "status": 0,
    "restante_segundos": 0
  }
}
400

Faltan los query params.

Ejemplo
{
  "error": "alerta_id y vehiculo_id son requeridos como query params"
}
403

La petición no viene de un sitio https://*.quro.com.mx (cabecera Origin). Lo contesta el nginx, sin cuerpo JSON.

404

No hay silencio activo para ese par.

Ejemplo
{
  "error": "No hay silencio activo para esa alerta/vehículo"
}
500

Error inesperado del servicio.

Ejemplo
{
  "error": "Error desconocido"
}
Ejemplo con curl
curl -X DELETE 'https://apiomi.silencio.quro.com.mx/api/alertas/silenciar?alerta_id=<alerta_id>&vehiculo_id=<vehiculo_id>' \
  -H 'Origin: https://tu-app.quro.com.mx'

Fuera de un navegador hay que mandar Origin de un sitio *.quro.com.mx; el navegador lo pone solo.

Ejemplo desde la app web (fetch)
const r = await fetch('https://apiomi.silencio.quro.com.mx/api/alertas/silenciar?alerta_id=<alerta_id>&vehiculo_id=<vehiculo_id>', {
  method: 'DELETE',
});
const datos = await r.json();   // { ok: true, ... } o { error: '...' }

DELETE /api/alertas/silenciar/{id}

Cancelar un silencio por su _id

Idempotente: cancelar uno ya cancelado devuelve el mismo silencio.

Parámetros

NombreDóndeObligatorioTipoQué es
idpathsístring

_id del silencio.

Cuerpo (JSON)

CampoObligatorioTipoQué es
cancelado_pornoobject

Quién hizo la acción (auditoría). Opcional. También se acepta un texto plano, o los campos planos <accion>_uid, <accion>_nombre y <accion>_email.

Respuestas

200

Silencio cancelado.

Ejemplo
{
  "ok": true,
  "silencio": {
    "_id": "670d5f1a2b3c4d5e6f708192",
    "uid_empresa": "66f1a2b3c4d5e6f708192a3b",
    "alerta_id": "69eb9d55a1b2c3d4e5f60718",
    "alerta_nombre": "DETENCIÓN DE UNIDAD",
    "vehiculo_id": "69c56400a1b2c3d4e5f60006",
    "vehiculo_alias": "TR-685",
    "vehiculo_uid_externo": null,
    "silenciada_desde": "2026-10-14T20:00:00.000Z",
    "silenciada_hasta": "2026-10-15T08:00:00.000Z",
    "horas": 12,
    "motivo": "Unidad en taller",
    "creado_por": {
      "uid": "0d8f1c2e-6b8a-4c7e-9a51-2f3e4d5c6b7a",
      "nombre": "Ana López",
      "email": "ana.lopez@empresa.com"
    },
    "creado_en": "2026-10-14T20:00:00.000Z",
    "cancelado_por": null,
    "cancelado_en": "2026-10-14T22:00:00.000Z",
    "expirado_en": null,
    "status": 0,
    "restante_segundos": 0
  }
}
400

id inválido.

Ejemplo
{
  "error": "ObjectId inválido: abc"
}
403

La petición no viene de un sitio https://*.quro.com.mx (cabecera Origin). Lo contesta el nginx, sin cuerpo JSON.

404

No existe.

Ejemplo
{
  "error": "Silencio no encontrado"
}
500

Error inesperado del servicio.

Ejemplo
{
  "error": "Error desconocido"
}
Ejemplo con curl
curl -X DELETE 'https://apiomi.silencio.quro.com.mx/api/alertas/silenciar/<id>' \
  -H 'Origin: https://tu-app.quro.com.mx'

Fuera de un navegador hay que mandar Origin de un sitio *.quro.com.mx; el navegador lo pone solo.

Ejemplo desde la app web (fetch)
const r = await fetch('https://apiomi.silencio.quro.com.mx/api/alertas/silenciar/<id>', {
  method: 'DELETE',
});
const datos = await r.json();   // { ok: true, ... } o { error: '...' }

GET /api/alertas/silenciadas

Listar silencios (paginado)

Se requiere AL MENOS uno de uid_empresa o vehiculo_id.

Parámetros

NombreDóndeObligatorioTipoQué es
uid_empresaquerynostring

ObjectId (24 hex) de la empresa en la base de omisiones.

vehiculo_idquerynostring

ObjectId o UID_Externo.

alerta_idquerynostring
activasquerynoboolean (por defecto false)

true = sólo los activos.

pagequerynointeger (por defecto 1)
limitquerynointeger (por defecto 50)

Respuestas

200

Página de silencios.

Ejemplo
{
  "ok": true,
  "items": [
    {
      "_id": "670d5f1a2b3c4d5e6f708192",
      "uid_empresa": "66f1a2b3c4d5e6f708192a3b",
      "alerta_id": "69eb9d55a1b2c3d4e5f60718",
      "alerta_nombre": "DETENCIÓN DE UNIDAD",
      "vehiculo_id": "69c56400a1b2c3d4e5f60006",
      "vehiculo_alias": "TR-685",
      "vehiculo_uid_externo": null,
      "silenciada_desde": "2026-10-14T20:00:00.000Z",
      "silenciada_hasta": "2026-10-15T08:00:00.000Z",
      "horas": 12,
      "motivo": "Unidad en taller",
      "creado_por": {
        "uid": "0d8f1c2e-6b8a-4c7e-9a51-2f3e4d5c6b7a",
        "nombre": "Ana López",
        "email": "ana.lopez@empresa.com"
      },
      "creado_en": "2026-10-14T20:00:00.000Z",
      "cancelado_por": null,
      "cancelado_en": null,
      "expirado_en": null,
      "status": 1,
      "restante_segundos": 43200
    }
  ],
  "total": 1,
  "page": 1,
  "limit": 50
}
400

Falta el alcance, o un id no es un ObjectId válido.

Ejemplo
{
  "error": "se requiere uid_empresa o vehiculo_id (al menos uno)"
}
403

La petición no viene de un sitio https://*.quro.com.mx (cabecera Origin). Lo contesta el nginx, sin cuerpo JSON.

500

Error inesperado del servicio.

Ejemplo
{
  "error": "Error desconocido"
}
Ejemplo con curl
curl -X GET 'https://apiomi.silencio.quro.com.mx/api/alertas/silenciadas' \
  -H 'Origin: https://tu-app.quro.com.mx'

Fuera de un navegador hay que mandar Origin de un sitio *.quro.com.mx; el navegador lo pone solo.

Ejemplo desde la app web (fetch)
const r = await fetch('https://apiomi.silencio.quro.com.mx/api/alertas/silenciadas', {
  method: 'GET',
});
const datos = await r.json();   // { ok: true, ... } o { error: '...' }

GET /api/alertas/silenciadas/vehiculo/{vehiculo_id}

Silencios ACTIVOS de un vehículo

Parámetros

NombreDóndeObligatorioTipoQué es
vehiculo_idpathsístring

ObjectId o UID_Externo.

Respuestas

200

Silencios activos.

Ejemplo
{
  "ok": true,
  "items": [
    {
      "_id": "670d5f1a2b3c4d5e6f708192",
      "uid_empresa": "66f1a2b3c4d5e6f708192a3b",
      "alerta_id": "69eb9d55a1b2c3d4e5f60718",
      "alerta_nombre": "DETENCIÓN DE UNIDAD",
      "vehiculo_id": "69c56400a1b2c3d4e5f60006",
      "vehiculo_alias": "TR-685",
      "vehiculo_uid_externo": null,
      "silenciada_desde": "2026-10-14T20:00:00.000Z",
      "silenciada_hasta": "2026-10-15T08:00:00.000Z",
      "horas": 12,
      "motivo": "Unidad en taller",
      "creado_por": {
        "uid": "0d8f1c2e-6b8a-4c7e-9a51-2f3e4d5c6b7a",
        "nombre": "Ana López",
        "email": "ana.lopez@empresa.com"
      },
      "creado_en": "2026-10-14T20:00:00.000Z",
      "cancelado_por": null,
      "cancelado_en": null,
      "expirado_en": null,
      "status": 1,
      "restante_segundos": 43200
    }
  ]
}
403

La petición no viene de un sitio https://*.quro.com.mx (cabecera Origin). Lo contesta el nginx, sin cuerpo JSON.

404

El vehículo no existe (por UID_Externo).

Ejemplo
{
  "error": "Vehículo no encontrado por UID_Externo: b1c2d3e4-…"
}
500

Error inesperado del servicio.

Ejemplo
{
  "error": "Error desconocido"
}
Ejemplo con curl
curl -X GET 'https://apiomi.silencio.quro.com.mx/api/alertas/silenciadas/vehiculo/<vehiculo_id>' \
  -H 'Origin: https://tu-app.quro.com.mx'

Fuera de un navegador hay que mandar Origin de un sitio *.quro.com.mx; el navegador lo pone solo.

Ejemplo desde la app web (fetch)
const r = await fetch('https://apiomi.silencio.quro.com.mx/api/alertas/silenciadas/vehiculo/<vehiculo_id>', {
  method: 'GET',
});
const datos = await r.json();   // { ok: true, ... } o { error: '...' }

GET /health

Salud del servicio y de su base

Respuestas

200

Servicio y Mongo en línea.

Ejemplo
{
  "status": "ok",
  "service": "silenciado-api",
  "mongo": "online"
}
503

Mongo no responde.

Ejemplo
{
  "status": "error",
  "service": "silenciado-api",
  "mongo": "offline",
  "error": "…"
}

El objeto Silencio

CampoTipoQué es
_idstring

Identificador del silencio (ObjectId).

uid_empresastring

ObjectId de la empresa en la base de omisiones (24 hex).

alerta_idstring

ObjectId de la configuración de alerta.

alerta_nombrestring o null
vehiculo_idstring

ObjectId del vehículo.

vehiculo_aliasstring o null
vehiculo_uid_externostring o null
silenciada_desdestring

UTC.

silenciada_hastastring

UTC. Al pasar esta hora el silencio expira solo.

horasnumber
motivostring o null
creado_porobject o null

Quién hizo la acción (auditoría). Opcional. También se acepta un texto plano, o los campos planos <accion>_uid, <accion>_nombre y <accion>_email.

creado_enstring o null
cancelado_porobject o null

Quién hizo la acción (auditoría). Opcional. También se acepta un texto plano, o los campos planos <accion>_uid, <accion>_nombre y <accion>_email.

cancelado_enstring o null
expirado_enstring o null

Cuándo se detectó que venció.

statusinteger

1 = activo; 0 = cancelado o expirado.

restante_segundosinteger

Segundos que le quedan (0 si no está activo).