Cumplimiento
El dominio de cumplimiento (Compliance) agrupa los endpoints BFF que sostienen la evidencia regulatoria del club: el registro de auditoría de accesos y cambios (Res. AAIP 47/2018, Ley 25.326), el log de dispensación, el control del límite de pacientes (150, Res. 1780/2025), los plazos regulatorios próximos, los datos agregados del informe semestral REPROCANN y un resumen de estado de compliance de toda la organización.
Todas las rutas bajo /api/compliance son de solo lectura (GET) y requieren autenticación mediante Bearer JWT. El endpoint de auditoría exige además rol clínico/staff (los miembros quedan excluidos), y varias rutas resuelven el Tenant-id para aislar los datos por organización.
The audit log model
El registro de auditoría (ActivityLog) documenta quién hizo qué y cuándo a través de la organización. Es la evidencia de "registros aptos" de la Res. 1780/2025 y del registro de accesos/cambios de la Res. AAIP 47/2018.
Properties
- Name
id- Type
- string
- Description
Identificador del registro.
- Name
memberId- Type
- string
- Description
ID del miembro asociado al evento.
- Name
type- Type
- ActivityLogType
- Description
Tipo de evento. Valores posibles:
- STATUS_CHANGE
- DOCUMENT_UPLOAD
- DOCUMENT_DELETE
- NOTE_ADDED
- NOTE_DELETED
- DISPENSATION
- TRANSACTION
- MEMBERSHIP_CHANGE
- PROFILE_UPDATE
- MEDICAL_UPDATE
- MEMBER_CREATED
- APPOINTMENT_SCHEDULED
- APPOINTMENT_CONFIRMED
- APPOINTMENT_RESCHEDULED
- APPOINTMENT_CANCELLED
- APPOINTMENT_COMPLETED
- APPOINTMENT_NO_SHOW
- MEDICAL_ACCESS
- CONSENT_GRANTED
- CONSENT_WITHDRAWN
- DATA_EXPORTED
- DELETION_REQUESTED
- ACCOUNT_DELETED
- Name
label- Type
- string
- Description
Descripción legible del evento.
- Name
detail- Type
- string
- Description
Detalle adicional del evento.
- Name
metadata- Type
- object
- Description
Metadata arbitraria asociada al evento.
- Name
performedById- Type
- string
- Description
ID del actor que ejecutó la acción.
- Name
performedByName- Type
- string
- Description
Nombre del actor.
- Name
ipAddress- Type
- string
- Description
Dirección IP registrada.
- Name
userAgent- Type
- string
- Description
User agent registrado.
- Name
referenceId- Type
- string
- Description
ID de la entidad referenciada.
- Name
referenceType- Type
- enum
- Description
Tipo de entidad referenciada: ORDER, ATTACH, TRANSACTION, NOTE, MEMBER o APPOINTMENT.
- Name
createdAt- Type
- string
- Description
Timestamp del evento (ISO).
Activity log example
{
"id": "al-1",
"memberId": "usr_01HQ8XYZABC123",
"type": "MEDICAL_ACCESS",
"label": "Acceso a ficha médica",
"performedById": "staff-1",
"performedByName": "Dra. Ana Médica",
"ipAddress": "190.0.0.1",
"referenceId": "usr_01HQ8XYZABC123",
"referenceType": "MEMBER",
"createdAt": "2026-06-17T13:40:00.000Z"
}
Registro de auditoría
Retorna el registro de auditoría de toda la organización (accesos, cambios, dispensaciones, etc.). Restringido a roles staff/clínicos: el rol MEMBER queda excluido por el gate de acceso médico.
Si se omite memberId, la respuesta abarca todos los logs del tenant.
Query params opcionales
- Name
memberId- Type
- string
- Description
Filtra por miembro.
- Name
type- Type
- ActivityLogType
- Description
Filtra por tipo de evento (ver enum del modelo).
- Name
dateFrom- Type
- string
- Description
Fecha desde (ISO).
- Name
dateTo- Type
- string
- Description
Fecha hasta (ISO).
- Name
page- Type
- integer
- Description
Página.
- Name
limit- Type
- integer
- Description
Cantidad por página (default 500).
Request
curl -G https://api.cannahub.tech/api/compliance/audit-log \
-H "Authorization: Bearer {token}" \
-H "Tenant-id: {tenantId}" \
-d type=MEDICAL_ACCESS \
-d limit=500
Response
{
"activityLogs": [
{
"id": "al-1",
"memberId": "usr_01HQ8XYZABC123",
"type": "MEDICAL_ACCESS",
"label": "Acceso a ficha médica",
"performedById": "staff-1",
"performedByName": "Dra. Ana Médica",
"ipAddress": "190.0.0.1",
"referenceId": "usr_01HQ8XYZABC123",
"referenceType": "MEMBER",
"createdAt": "2026-06-17T13:40:00.000Z"
}
],
"count": 1
}
Registro de dispensación
Retorna los registros de dispensación (items de órdenes con información de paciente y lote) para el seguimiento de la distribución de productos. Cada item de cada orden dentro del rango se transforma en un registro individual.
Query params opcionales
- Name
from- Type
- string
- Description
Fecha desde (YYYY-MM-DD). Filtra por
created_atde la orden.
- Name
to- Type
- string
- Description
Fecha hasta (YYYY-MM-DD).
Campos de cada registro
- Name
date- Type
- string
- Description
- Fecha de la orden (ISO).
- Name
patientName- Type
- string
- Description
- Nombre del paciente.
- Name
patientDni- Type
- string
- Description
- DNI del paciente.
- Name
reprocannCode- Type
- string
- Description
- Código REPROCANN del paciente.
- Name
productName- Type
- string
- Description
- Nombre del producto dispensado.
- Name
quantity- Type
- number
- Description
- Cantidad.
- Name
unit- Type
- string
- Description
- Unidad (default
g).
- Name
batchNumber- Type
- string
- Description
- Número de lote.
- Name
strainName- Type
- string
- Description
- Nombre de la cepa.
- Name
authorizedBy- Type
- string
- Description
- Autorizante de la dispensación.
- Name
orderId- Type
- string | number
- Description
- ID (o displayId) de la orden.
Request
curl -G https://api.cannahub.tech/api/compliance/dispensation \
-H "Authorization: Bearer {token}" \
-d from=2025-01-01 \
-d to=2025-06-30
Response
{
"records": [
{
"date": "2025-03-15T14:30:00Z",
"patientName": "María González",
"patientDni": "35123456",
"reprocannCode": "REPRO-2024-AR-001234",
"productName": "Blue Dream 3.5g",
"quantity": 2,
"unit": "g",
"batchNumber": "B-2025-014",
"strainName": "Blue Dream",
"authorizedBy": "Dra. Ana Médica",
"orderId": 1234
}
],
"count": 1
}
Límite de pacientes
Retorna la cantidad actual de pacientes y el máximo permitido. El máximo es 150 (Res. 1780/2025).
Response
- Name
current- Type
- number
- Description
Cantidad actual de pacientes registrados.
- Name
maximum- Type
- number
- Description
Máximo permitido (150).
Request
curl https://api.cannahub.tech/api/compliance/patient-limit \
-H "Authorization: Bearer {token}"
Response
{
"current": 42,
"maximum": 150
}
Plazos regulatorios
Agrega los plazos de cumplimiento regulatorio y operativo próximos: informe semestral, renovaciones REPROCANN (miembros y cultivos que vencen dentro de 60 días), vencimiento de la matrícula del director médico y renovaciones de variedades INASE RNC. Los plazos se ordenan por fecha ascendente.
Campos de cada plazo
- Name
id- Type
- string
- Description
- Identificador del plazo.
- Name
date- Type
- string
- Description
- Fecha de vencimiento (YYYY-MM-DD).
- Name
label- Type
- string
- Description
- Etiqueta del plazo.
- Name
description- Type
- string
- Description
- Descripción del plazo.
- Name
tag- Type
- string
- Description
Texto relativo calculado:
Vencido,Vence hoyoEn {n} días.
- Name
urgency- Type
- enum
- Description
Urgencia calculada según los días restantes:
- urgent: 14 días o menos
- soon: entre 15 y 30 días
- normal: más de 30 días
Request
curl https://api.cannahub.tech/api/compliance/deadlines \
-H "Authorization: Bearer {token}"
Response
{
"deadlines": [
{
"id": "reprocann-renewals",
"date": "2026-07-15",
"label": "Renovación REPROCANN",
"description": "7 documentos vencen en los próximos 60 días.",
"tag": "En 9 días",
"urgency": "urgent"
},
{
"id": "medical-director-matricula",
"date": "2026-07-28",
"label": "Matrícula Director Médico",
"description": "Vencimiento de la matrícula del director médico designado.",
"tag": "En 22 días",
"urgency": "soon"
},
{
"id": "semi-annual-report",
"date": "2026-12-31",
"label": "Informe Semestral",
"description": "Res. 1780/2025 - presentación obligatoria del informe del semestre.",
"tag": "En 45 días",
"urgency": "normal"
}
]
}
Informe semestral
Retorna los datos agregados necesarios para el informe semestral REPROCANN. Combina información de miembros, cultivos, cosechas, prescripciones, plantas y organización para el período indicado.
El período se deriva del semester (1 = 1 ene – 30 jun; 2 = 1 jul – 31 dic) y del year. Si semester no es 1 ni 2, la respuesta es un error de validación (400).
Query params opcionales
- Name
semester- Type
- integer
- Description
Semestre:
1o2(default1).
- Name
year- Type
- integer
- Description
Año (default: año actual).
Response
- Name
semester- Type
- number
- Description
- Semestre solicitado.
- Name
year- Type
- number
- Description
- Año solicitado.
- Name
from- Type
- string
- Description
- Inicio del período (YYYY-MM-DD).
- Name
to- Type
- string
- Description
- Fin del período (YYYY-MM-DD).
- Name
members- Type
- array
- Description
Miembros con su ficha médica (reprocannCode, reprocannExpiration, cannabisUses, etc.).
- Name
harvests- Type
- array
- Description
Cosechas del período con cannabinoides y análisis de laboratorio.
- Name
prescriptions- Type
- array
- Description
Prescripciones (patientId + products).
- Name
plants- Type
- array
- Description
Plantas con su estado.
- Name
crops- Type
- array
- Description
Cultivos con datos de cepa (incl. inaseRegistrationNumber).
- Name
organization- Type
- object
- Description
Datos de la organización, incluyendo director médico y responsable técnico.
Request
curl -G https://api.cannahub.tech/api/compliance/semi-annual \
-H "Authorization: Bearer {token}" \
-d semester=1 \
-d year=2025
Response
{
"semester": 1,
"year": 2025,
"from": "2025-01-01",
"to": "2025-06-30",
"members": [
{
"id": "usr_01HQ8XYZABC123",
"firstName": "María",
"lastName": "González",
"document": "35123456",
"medicalRecord": {
"reprocannCode": "REPRO-2024-AR-001234",
"reprocannExpiration": "2025-01-15",
"cannabisUses": ["Manejo de ansiedad"]
}
}
],
"harvests": [
{
"id": "harv_01",
"name": "Cosecha Sala A - Q1",
"batchNumber": "B-2025-014",
"harvestedAt": "2025-03-20",
"strainName": "Charlotte Web",
"cannabinoids": { "thc": 0.5, "cbd": 14.2 },
"labAnalysis": {
"labName": "Laboratorio Cannábico Nacional",
"analysisDate": "2025-03-28"
}
}
],
"prescriptions": [],
"plants": [
{ "id": "p1", "status": "FLOWERING" },
{ "id": "p2", "status": "VEGETATING" }
],
"crops": [
{
"id": "c1",
"name": "Cultivo 1",
"strain": { "name": "Charlotte Web", "type": "CBD" }
}
],
"organization": {
"name": "Medicann Demo",
"medicalDirector": { "name": "Dr. Mock", "matricula": "12345" }
}
}
Resumen de cumplimiento
Agrega datos de cumplimiento desde múltiples fuentes (miembros, plantas, cultivos, cosechas, espacios, staff, órdenes y productos) para ofrecer una vista general del estado regulatorio de la organización. Base del dashboard de compliance.
Response
- Name
members- Type
- object
- Description
Resumen de miembros.
- Name
total- Type
- number
- Description
- Total de miembros.
- Name
withActiveReprocann- Type
- number
- Description
- Con REPROCANN vigente.
- Name
withExpiredReprocann- Type
- number
- Description
- Con REPROCANN vencido.
- Name
withInformedConsent- Type
- number
- Description
- Con consentimiento informado.
- Name
list- Type
- array
- Description
Lista de miembros (id, name, dni, reprocannCode, reprocannExpiration, initials, avatarTone, hasInformedConsent).
- Name
plants- Type
- object
- Description
Conteo de plantas por estado (total, flowering, vegetative, other).
- Name
crops- Type
- object
- Description
Cultivos (total, withInaseRegisteredStrain, withoutInaseRegisteredStrain).
- Name
harvests- Type
- object
- Description
Cosechas (total, withCannabinoids, withLabAnalysis, withBatchNumber, batchesPendingAnalysis).
- Name
spaces- Type
- object
- Description
Espacios (total, withGeolocation).
- Name
organization- Type
- object
- Description
Organización (name, hasMedicalDirector, hasTechnicalManager, patientsMax, locationsMax).
- Name
orders- Type
- object
- Description
Órdenes (total, toRegisteredPatients).
- Name
products- Type
- object
- Description
Productos (total, withCannabinoidLabel).
- Name
lastSyncedAt- Type
- string
- Description
Timestamp de la agregación (ISO).
Request
curl https://api.cannahub.tech/api/compliance/summary \
-H "Authorization: Bearer {token}"
Response
{
"members": {
"total": 42,
"withActiveReprocann": 38,
"withExpiredReprocann": 3,
"withInformedConsent": 40,
"list": [
{
"id": "mock-mem-1",
"name": "Lucía Fernández",
"dni": "32145678",
"reprocannCode": "RC-00012",
"reprocannExpiration": "2026-11-12",
"initials": "LF",
"avatarTone": "a",
"hasInformedConsent": true
}
]
},
"plants": { "total": 180, "flowering": 45, "vegetative": 90, "other": 45 },
"crops": { "total": 8, "withInaseRegisteredStrain": 5, "withoutInaseRegisteredStrain": 3 },
"harvests": {
"total": 12,
"withCannabinoids": 9,
"withLabAnalysis": 6,
"withBatchNumber": 11,
"batchesPendingAnalysis": ["B-2026-007", "B-2026-009", "B-2026-011"]
},
"spaces": { "total": 3, "withGeolocation": 1 },
"organization": {
"name": "Medicann Demo",
"hasMedicalDirector": true,
"hasTechnicalManager": false,
"patientsMax": 150,
"locationsMax": 3
},
"orders": { "total": 85, "toRegisteredPatients": 82 },
"products": { "total": 15, "withCannabinoidLabel": 12 },
"lastSyncedAt": "2026-06-17T18:00:00.000Z"
}