API de silencios de alertas (omisiones)
https://apiomi.silencio.quro.com.mxSilencia una alerta para un vehículo durante N horas: mientras dure, el motor de omisiones NO la notifica a ese vehículo.
- Las fechas van en UTC (ISO 8601). El cliente sólo manda la duración en
horas(0 < horas ≤ 720). - Silenciar la misma alerta para el mismo vehículo otra vez reinicia la duración (no crea un duplicado).
- Un silencio vence solo; también se puede cancelar antes (por su
_ido por el par alerta + vehículo). - Acceso: sólo desde aplicaciones web servidas en
https://*.quro.com.mx(el navegador manda la cabeceraOrigin; sin unOriginpermitido la respuesta es 403)./health,/docsy/openapi.jsonson públicos.
Cómo implementarlo, en 4 pasos
- Silenciar:
POST /api/alertas/silenciarconalerta_id,vehiculo_id,uid_empresayhoras. Guarda el_idque regresa. - Mostrar lo silenciado:
GET /api/alertas/silenciadas?uid_empresa=…&activas=true(paginado) oGET /api/alertas/silenciadas/vehiculo/{vehiculo_id}. Usarestante_segundospara el contador. - 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=…. - Auditoría: manda siempre
creado_por/cancelado_porcon{ 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)
| Campo | Obligatorio | Tipo | Qué es |
|---|---|---|---|
alerta_id | sí | string | ObjectId de la alerta (configuración) a silenciar. |
vehiculo_id | sí | string | ObjectId del vehículo o su UID_Externo (el que usa el panel). |
uid_empresa | sí | 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. |
horas | sí | number (máx. 720) | Duración en horas (máximo 720). |
motivo | no | string (hasta 200 car.) | Opcional, hasta 200 caracteres. |
creado_por | no | object | Quién hizo la acción (auditoría). Opcional. También se acepta un texto plano, o los campos planos |
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 |
| 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
| Nombre | Dónde | Obligatorio | Tipo | Qué es |
|---|---|---|---|---|
alerta_id | query | sí | string | |
vehiculo_id | query | sí | string | ObjectId o UID_Externo. |
Cuerpo (JSON)
| Campo | Obligatorio | Tipo | Qué es |
|---|---|---|---|
cancelado_por | no | object | Quién hizo la acción (auditoría). Opcional. También se acepta un texto plano, o los campos planos |
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 |
| 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
| Nombre | Dónde | Obligatorio | Tipo | Qué es |
|---|---|---|---|---|
id | path | sí | string |
|
Cuerpo (JSON)
| Campo | Obligatorio | Tipo | Qué es |
|---|---|---|---|
cancelado_por | no | object | Quién hizo la acción (auditoría). Opcional. También se acepta un texto plano, o los campos planos |
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 |
| 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
| Nombre | Dónde | Obligatorio | Tipo | Qué es |
|---|---|---|---|---|
uid_empresa | query | no | string | ObjectId (24 hex) de la empresa en la base de omisiones. |
vehiculo_id | query | no | string | ObjectId o UID_Externo. |
alerta_id | query | no | string | |
activas | query | no | boolean (por defecto false) |
|
page | query | no | integer (por defecto 1) | |
limit | query | no | integer (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 |
| 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
| Nombre | Dónde | Obligatorio | Tipo | Qué es |
|---|---|---|---|---|
vehiculo_id | path | sí | 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 |
| 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
| Campo | Tipo | Qué es |
|---|---|---|
_id | string | Identificador del silencio (ObjectId). |
uid_empresa | string | ObjectId de la empresa en la base de omisiones (24 hex). |
alerta_id | string | ObjectId de la configuración de alerta. |
alerta_nombre | string o null | |
vehiculo_id | string | ObjectId del vehículo. |
vehiculo_alias | string o null | |
vehiculo_uid_externo | string o null | |
silenciada_desde | string | UTC. |
silenciada_hasta | string | UTC. Al pasar esta hora el silencio expira solo. |
horas | number | |
motivo | string o null | |
creado_por | object o null | Quién hizo la acción (auditoría). Opcional. También se acepta un texto plano, o los campos planos |
creado_en | string o null | |
cancelado_por | object o null | Quién hizo la acción (auditoría). Opcional. También se acepta un texto plano, o los campos planos |
cancelado_en | string o null | |
expirado_en | string o null | Cuándo se detectó que venció. |
status | integer | 1 = activo; 0 = cancelado o expirado. |
restante_segundos | integer | Segundos que le quedan (0 si no está activo). |