API de Gestión de Riesgos
El módulo de Gestión de Riesgos está disponible en todos los planes. Los límites de registros son: Starter 30 riesgos, Professional 100, Business y Enterprise ilimitados. Consulta la guía funcional del módulo para más contexto.
El módulo de riesgos implementa una matriz de evaluación 5×5 probabilidad × impacto (escala 1 a 5 para cada dimensión), produciendo un puntaje de riesgo entre 1 y 25. Los riesgos se categorizan según las dimensiones clave del estándar ISO 27701 §6.3 adaptadas a la Ley 21.719.
Base URL: https://api.dpolab.com/api/v1/risks
Resumen de endpoints
| Método | Endpoint | Rol mínimo | Descripción |
|---|---|---|---|
GET | /risks | VIEWER | Listar riesgos con paginación |
POST | /risks | ANALYST+ | Crear riesgo |
GET | /risks/:id | VIEWER | Obtener detalle de riesgo |
PUT | /risks/:id | ANALYST+ | Actualizar riesgo |
DELETE | /risks/:id | ADMIN | Eliminar riesgo (soft delete) |
GET | /risks/heatmap | VIEWER | Mapa de calor 5×5 |
GET | /risks/stats | VIEWER | Estadísticas globales |
GET | /risks/threats | VIEWER | Catálogo de amenazas |
POST | /risks/:id/action-plans | ANALYST+ | Crear plan de acción |
PUT | /risks/:id/action-plans/:planId | ANALYST+ | Actualizar plan de acción |
DELETE | /risks/:id/action-plans/:planId | ANALYST+ | Eliminar plan de acción |
Riesgos
Listar riesgos
GET /risksRetorna riesgos ordenados por puntaje descendente (mayor riesgo primero). Cada entrada incluye el asignado responsable si lo tiene.
Query params opcionales:
| Param | Tipo | Descripción |
|---|---|---|
legalEntityId | UUID | Filtrar por entidad legal |
category | enum | Ver categorías disponibles abajo |
status | enum | IDENTIFIED, ANALYZING, TREATING, MONITORED, CLOSED |
dpiaId | UUID | Filtrar riesgos vinculados a una DPIA específica |
minScore | integer (1-25) | Puntaje mínimo (usa el puntaje actual si existe, si no el inicial) |
maxScore | integer (1-25) | Puntaje máximo |
page | integer | Default: 1 |
limit | integer (máx. 100) | Default: 20 |
curl "https://api.dpolab.com/api/v1/risks?category=PRIVACY_RIGHTS&minScore=10" \
-H "Authorization: Bearer {token}"Respuesta (200):
{
"success": true,
"data": {
"risks": [
{
"id": "risk_001",
"legalEntityId": "entity_xyz",
"title": "Acceso no autorizado a datos de clientes",
"category": "CONFIDENTIALITY",
"subcategory": "Control de acceso",
"threatRef": "T-003",
"probability": 3,
"impact": 5,
"riskScoreInitial": 15,
"probabilityCurrent": null,
"impactCurrent": null,
"riskScoreCurrent": null,
"probabilityResidual": null,
"impactResidual": null,
"riskScoreResidual": null,
"status": "TREATING",
"treatment": "MITIGATE",
"dpiaId": null,
"dpiaRequired": false,
"assignee": {
"userId": "usr_abc",
"name": "María González",
"email": "[email protected]"
},
"createdAt": "2026-04-01T09:00:00Z",
"updatedAt": "2026-05-10T14:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 8
}
}
}Crear riesgo
POST /risksRequiere rol ANALYST o superior. Sujeto al límite del plan.
Los riesgos con puntaje inicial igual o superior a 10 generan automáticamente una tarea de seguimiento para el equipo de cumplimiento.
curl -X POST https://api.dpolab.com/api/v1/risks \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"legalEntityId": "entity_xyz",
"title": "Acceso no autorizado a datos de clientes",
"description": "Riesgo de acceso indebido a la base de datos de CRM por personal sin autorización.",
"category": "CONFIDENTIALITY",
"subcategory": "Control de acceso",
"threatRef": "T-003",
"probability": 3,
"impact": 5,
"dpiaRequired": false,
"treatment": "MITIGATE"
}'| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
legalEntityId | UUID | Sí | Entidad legal responsable |
title | string (2-300 chars) | Sí | Título del riesgo |
description | string (máx. 5000 chars) | No | Descripción detallada (cifrada en reposo) |
category | enum | Sí | Ver categorías abajo |
subcategory | string (máx. 200 chars) | No | Subcategoría libre |
threatRef | string (máx. 50 chars) | No | Código de amenaza del catálogo (p. ej. T-003) |
probability | integer (1-5) | Sí | Probabilidad de ocurrencia |
impact | integer (1-5) | Sí | Impacto si ocurre |
dpiaId | UUID | No | DPIA asociada |
dpiaRequired | boolean | No | Indica si este riesgo requiere DPIA |
treatment | enum | No | ACCEPT, MITIGATE, TRANSFER, AVOID |
Respuesta (201):
{
"success": true,
"data": {
"risk": {
"id": "risk_new009",
"title": "Acceso no autorizado a datos de clientes",
"probability": 3,
"impact": 5,
"riskScoreInitial": 15,
"status": "IDENTIFIED",
"createdAt": "2026-05-24T10:00:00Z"
}
}
}Obtener detalle de riesgo
GET /risks/:idRetorna el riesgo completo incluyendo description (descifrada), todos los puntajes (inicial, actual, residual) y metadatos.
curl https://api.dpolab.com/api/v1/risks/risk_001 \
-H "Authorization: Bearer {token}"Actualizar riesgo
PUT /risks/:idRequiere rol ANALYST o superior. Acepta los mismos campos que la creación más los puntajes actuales y residuales. Solo envía los campos que quieras modificar.
curl -X PUT https://api.dpolab.com/api/v1/risks/risk_001 \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"probabilityCurrent": 2,
"impactCurrent": 5,
"probabilityResidual": 1,
"impactResidual": 3,
"status": "MONITORED",
"treatment": "MITIGATE"
}'| Campo adicional | Tipo | Descripción |
|---|---|---|
probabilityCurrent | integer (1-5) o null | Probabilidad tras medidas implementadas |
impactCurrent | integer (1-5) o null | Impacto tras medidas implementadas |
probabilityResidual | integer (1-5) o null | Probabilidad residual esperada |
impactResidual | integer (1-5) o null | Impacto residual esperado |
status | enum | IDENTIFIED, ANALYZING, TREATING, MONITORED, CLOSED |
El sistema calcula automáticamente riskScoreCurrent = probabilityCurrent × impactCurrent y riskScoreResidual = probabilityResidual × impactResidual cuando se envían esos campos.
Eliminar riesgo
DELETE /risks/:idRequiere rol ADMIN. Los riesgos se mantienen para auditoría incluso al eliminarlos (soft delete). El estado pasa a CLOSED y se marca como eliminado.
Mapa de calor
GET /risks/heatmapRetorna la distribución de riesgos en la matriz 5×5. Solo incluye riesgos que no están en estado CLOSED. Usa el puntaje actual si existe; si no, el puntaje inicial.
Query params opcionales:
| Param | Descripción |
|---|---|
legalEntityId | Filtrar por entidad legal |
curl "https://api.dpolab.com/api/v1/risks/heatmap?legalEntityId=entity_xyz" \
-H "Authorization: Bearer {token}"Respuesta (200):
{
"success": true,
"data": {
"matrix": [
[0, 1, 0, 0, 0],
[0, 0, 2, 1, 0],
[1, 0, 0, 0, 1],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0]
],
"risks": [
{
"id": "risk_001",
"title": "Acceso no autorizado a datos de clientes",
"probability": 3,
"impact": 5,
"score": 15,
"status": "TREATING",
"category": "CONFIDENTIALITY"
}
]
}
}La matrix es un arreglo de 5×5 donde matrix[impacto-1][probabilidad-1] contiene el número de riesgos en esa celda. Impacto y probabilidad van de 1 (bajo) a 5 (muy alto), siendo matrix[4][4] la celda de mayor criticidad (probabilidad 5, impacto 5).
Estadísticas
GET /risks/statsQuery params opcionales: legalEntityId.
curl https://api.dpolab.com/api/v1/risks/stats \
-H "Authorization: Bearer {token}"Respuesta (200):
{
"success": true,
"data": {
"total": 14,
"avgScore": 11.2,
"avgInitialScore": 12.8,
"byCategory": {
"CONFIDENTIALITY": 5,
"INTEGRITY": 2,
"AVAILABILITY": 1,
"PRIVACY_RIGHTS": 4,
"PHYSICAL": 0,
"THIRD_PARTY": 1,
"LEGAL_REGULATORY": 1
},
"byStatus": {
"IDENTIFIED": 3,
"ANALYZING": 2,
"TREATING": 5,
"MONITORED": 3,
"CLOSED": 1
},
"remediationPct": 22,
"highRiskCount": 4
}
}| Campo | Descripción |
|---|---|
avgScore | Promedio del puntaje actual (o inicial si no hay actual) |
avgInitialScore | Promedio del puntaje inicial en todos los riesgos |
remediationPct | Reducción porcentual del puntaje inicial al residual (solo riesgos con score residual registrado) |
highRiskCount | Riesgos activos con puntaje actual ≥ 15 (zona roja de la matriz) |
Catálogo de amenazas
GET /risks/threatsRetorna el catálogo de amenazas predefinidas del sistema. Los campos ref y title se pueden usar como referencia en el campo threatRef al crear un riesgo.
curl https://api.dpolab.com/api/v1/risks/threats \
-H "Authorization: Bearer {token}"Respuesta (200):
{
"success": true,
"data": {
"threats": [
{
"id": "threat_001",
"ref": "T-001",
"title": "Acceso no autorizado a sistemas",
"category": "CONFIDENTIALITY",
"isDefault": true
},
{
"id": "threat_002",
"ref": "T-002",
"title": "Pérdida o robo de dispositivos",
"category": "CONFIDENTIALITY",
"isDefault": true
}
]
}
}Planes de acción
Cada riesgo puede tener múltiples planes de acción para gestionar su tratamiento.
Crear plan de acción
POST /risks/:id/action-plansRequiere rol ANALYST o superior.
curl -X POST https://api.dpolab.com/api/v1/risks/risk_001/action-plans \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"title": "Implementar autenticación multifactor en CRM",
"description": "Activar MFA para todos los usuarios con acceso a datos de clientes.",
"dueDate": "2026-07-31",
"status": "PENDING"
}'| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
title | string (2-300 chars) | Sí | Acción concreta a tomar |
description | string (máx. 5000 chars) | No | Detalle de implementación |
dueDate | string YYYY-MM-DD | No | Fecha límite |
status | enum | No | PENDING, IN_PROGRESS, COMPLETED, CANCELLED — default: PENDING |
Respuesta (201):
{
"success": true,
"data": {
"actionPlan": {
"id": "plan_001",
"riskId": "risk_001",
"title": "Implementar autenticación multifactor en CRM",
"dueDate": "2026-07-31",
"status": "PENDING",
"createdAt": "2026-05-24T10:00:00Z"
}
}
}Actualizar plan de acción
PUT /risks/:id/action-plans/:planIdAcepta los mismos campos que la creación. Solo envía los campos que quieras modificar.
curl -X PUT https://api.dpolab.com/api/v1/risks/risk_001/action-plans/plan_001 \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{ "status": "COMPLETED" }'Eliminar plan de acción
DELETE /risks/:id/action-plans/:planIdEliminación permanente.
curl -X DELETE https://api.dpolab.com/api/v1/risks/risk_001/action-plans/plan_001 \
-H "Authorization: Bearer {token}"Categorías de riesgo
| Categoría | Descripción |
|---|---|
CONFIDENTIALITY | Acceso o divulgación no autorizados de datos personales |
INTEGRITY | Alteración, corrupción o modificación no autorizada |
AVAILABILITY | Pérdida de acceso o disponibilidad del dato |
PRIVACY_RIGHTS | Incumplimiento de derechos ARSOP o bases legales |
PHYSICAL | Pérdida de dispositivos, acceso físico no autorizado |
THIRD_PARTY | Riesgos asociados a encargados, subencargados o proveedores |
LEGAL_REGULATORY | Incumplimiento normativo (Ley 21.719, GDPR, sectorial) |
Estados de riesgo
| Estado | Descripción |
|---|---|
IDENTIFIED | Riesgo identificado, pendiente de análisis |
ANALYZING | En evaluación de probabilidad e impacto |
TREATING | Con planes de acción activos en ejecución |
MONITORED | Tratamiento completado, en seguimiento continuo |
CLOSED | Riesgo cerrado (eliminado o aceptado definitivamente) |
Interpretación de la matriz 5×5
| Puntaje | Nivel | Acción recomendada |
|---|---|---|
| 1-4 | Bajo | Monitorear periódicamente |
| 5-9 | Moderado | Gestionar con plan de acción |
| 10-14 | Alto | Atención prioritaria, plazo definido |
| 15-25 | Crítico | Acción inmediata, posible DPIA requerida |
Los riesgos con puntaje inicial ≥ 10 generan automáticamente una tarea de seguimiento en el módulo de tareas. Los riesgos con dpiaRequired: true aparecen como recomendación en el screening de DPIA.
Ver también
- Módulo Riesgos — Guía funcional con flujos y capturas
- API de DPIA — Evaluaciones de impacto vinculables a riesgos