Documentación técnica

API de integración de NexaLab

Conecta los módulos del laboratorio con tu ERP, SAP, Power Apps o cualquier otro sistema. 102 operaciones REST sobre inventario, equipos, muestras, resultados, compras, cumplimiento, incidencias, alertas, educación, investigación y trazabilidad.

Empezar

La integración va en dos direcciones, y una implementación completa suele usar las dos.

De tu sistema hacia NexaLab

Un gateway REST en /api/v1: consulta existencias, crea solicitudes de compra, registra recepciones.

De NexaLab hacia tu sistema

Webhooks firmados: NexaLab avisa en el momento en que algo ocurre, sin que tengas que preguntar cada rato.

Los tres pasos

  1. Pide la credencial. La emite un administrador del laboratorio desde Integraciones → Credenciales. Recibirás un client_id y una clave secreta que solo se muestra una vez.
  2. Comprueba que funciona. Llama a GET /api/v1/me: te dice el laboratorio, los alcances concedidos y la lista exacta de operaciones que tienes permitidas.
  3. Integra. Usa el spec OpenAPI para generar un cliente, o llama directo con la cabecera X-API-Key.
curl -H "X-API-Key: nxk_live_…" \
  https://nexalaboratories.com/api/v1/me

Autenticación

La misma credencial se presenta de dos formas. Elige la que soporte tu plataforma; no conceden nada distinto.

Opción A — Clave directa

Lo que usan Power Apps, la mayoría de ERP y cualquier herramienta que sepa poner una cabecera fija.

GET /api/v1/inventory/items
X-API-Key: nxk_live_…

También se acepta Authorization: Bearer nxk_live_….

Opción B — OAuth2 client_credentials

Para SAP y plataformas corporativas que prohíben guardar un secreto permanente en el cliente. El token dura una hora.

curl -X POST https://nexalaboratories.com/api/v1/oauth/token \
  -d "grant_type=client_credentials" \
  -d "client_id=nxc_…" \
  -d "client_secret=nxk_live_…"

{
  "access_token": "eyJhbGciOi…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "inventory:read purchasing:write"
}

El secreto se muestra una sola vez. NexaLab guarda solo su huella criptográfica. Si se pierde, se rota desde el panel: se emite uno nuevo y el anterior deja de servir en el acto.

Modelo de permisos

Tres reglas gobiernan todo lo que puede hacer una integración.

  1. Una credencial pertenece a un laboratorio. Una institución con tres laboratorios emite tres credenciales. El alcance nunca es ambiguo.
  2. Una credencial nunca puede hacer más que una persona identificable. Sus permisos efectivos son la intersección de los alcances concedidos con lo que puede hacer hoy el usuario responsable de esa credencial. Conceder inventory:write a una credencial cuyo responsable solo puede leer inventario no habilita nada.
  3. Todo queda en la bitácora. Una solicitud de compra creada por SAP pasa por las mismas validaciones, los mismos flujos y el mismo registro de auditoría que una creada a mano. No existe un camino «de servicio» que se salte reglas.

Consecuencia práctica: si el usuario responsable deja la institución o pierde el acceso al laboratorio, la integración deja de funcionar. Es deliberado. Antes de que alguien se vaya, traspasa sus credenciales.

Operaciones

102 operaciones agrupadas por módulo. Cada una indica el alcance que necesita. Todas cuelgan de https://nexalaboratories.com/api/v1.

Inventario

MétodoRutaQué haceAlcance
GET/inventory/itemsLista los artículos de inventario activos con existencia, lote y vencimiento.inventory:read
POST/inventory/itemsDa de alta un artículo de inventario y genera su etiqueta QR.inventory:write
GET/inventory/items/{id}Obtiene el detalle completo de un artículo de inventario.inventory:read
PATCH/inventory/items/{id}Actualiza los datos de un artículo de inventario.inventory:write
POST/inventory/items/{id}/discardRegistra la baja o descarte de un artículo de inventario.inventory:write
GET/inventory/movementsKardex de movimientos de existencia (solo anexado).inventory:read
POST/inventory/movementsRegistra una entrada, salida o ajuste de existencia.inventory:write
GET/inventory/controlledArtículos marcados como reactivo controlado, de doble uso o precursor.inventory:read
GET/inventory/controlled/requestsSolicitudes de autorización de uso de reactivo controlado.inventory:read
POST/inventory/controlled/requestsCrea una solicitud de uso de reactivo controlado.inventory:write
PATCH/inventory/controlled/requests/{id}Resuelve (autoriza o rechaza) una solicitud de uso controlado.inventory:write

Datos maestros

MétodoRutaQué haceAlcance
GET/inventory/categoriesCategorías de inventario, para mapear contra las del ERP.catalog:read
POST/inventory/categoriesCrea una categoría de inventario.inventory:write
PATCH/inventory/categoriesActualiza una categoría de inventario.inventory:write
GET/locationsUbicaciones de almacenamiento del laboratorio.catalog:read
POST/locationsCrea una ubicación de almacenamiento.inventory:write

Equipos

MétodoRutaQué haceAlcance
GET/equipmentEquipos del laboratorio con estado, calibración y próximo mantenimiento.equipment:read
POST/equipmentDa de alta un equipo.equipment:write
GET/equipment/{id}Detalle de un equipo.equipment:read
PATCH/equipment/{id}Actualiza los datos de un equipo.equipment:write
GET/equipment/eventsEventos de equipo: calibraciones, mantenimientos y verificaciones.equipment:read
POST/equipment/eventsRegistra un evento de calibración o mantenimiento.equipment:write
GET/equipment/plansPlanes de mantenimiento y calibración programados.equipment:read
POST/equipment/plansCrea un plan de mantenimiento o calibración.equipment:write
GET/equipment/plans/{id}Detalle de un plan de mantenimiento.equipment:read
PATCH/equipment/plans/{id}Actualiza un plan de mantenimiento.equipment:write
DELETE/equipment/plans/{id}Elimina un plan de mantenimiento.equipment:write
GET/equipment/certificatesCertificados de calibración registrados.equipment:read
POST/equipment/certificatesRegistra un certificado de calibración.equipment:write

Muestras

MétodoRutaQué haceAlcance
GET/specimensMuestras recibidas con su estado en el flujo de trabajo.specimens:read
POST/specimensRecibe una muestra y genera su número de acceso.specimens:write
POST/specimens/{id}/transitionsMueve una muestra al siguiente estado del flujo configurado.specimens:write

Resultados

MétodoRutaQué haceAlcance
GET/resultsResultados registrados con su método, versión y estado.results:read
POST/resultsRegistra un resultado analítico.results:write

Compras

MétodoRutaQué haceAlcance
GET/purchasing/requestsSolicitudes de compra con su estado de aprobación.purchasing:read
POST/purchasing/requestsCrea una solicitud de compra.purchasing:write
GET/purchasing/requests/{id}Detalle de una solicitud de compra con sus renglones.purchasing:read
PATCH/purchasing/requests/{id}Actualiza o cambia el estado de una solicitud de compra.purchasing:write

Cumplimiento

MétodoRutaQué haceAlcance
GET/complianceResumen del estado de cumplimiento del laboratorio.compliance:read
GET/compliance/catalogCatálogo de sustancias con CAS, clasificación y requisitos.compliance:read
POST/compliance/catalogAñade una sustancia al catálogo de reactivos.compliance:write
GET/compliance/catalog/{id}Detalle de una sustancia del catálogo.compliance:read
PATCH/compliance/catalog/{id}Actualiza una sustancia del catálogo.compliance:write
GET/compliance/permitsLicencias y permisos vigentes del laboratorio.compliance:read
POST/compliance/permitsRegistra una licencia o permiso.compliance:write
PATCH/compliance/permitsActualiza una licencia o permiso.compliance:write
GET/compliance/receiptsRecepciones con factura, orden de compra, licencia y permiso.compliance:read
POST/compliance/receiptsRegistra la recepción documentada de material controlado.compliance:write
GET/compliance/countsConteos físicos de existencia realizados.compliance:read
POST/compliance/countsAbre un conteo físico de existencia.compliance:write
GET/compliance/counts/{id}Detalle de un conteo físico y sus diferencias.compliance:read
PATCH/compliance/counts/{id}Actualiza o cierra un conteo físico.compliance:write
GET/compliance/disposalsDestrucciones y disposiciones registradas.compliance:read
POST/compliance/disposalsRegistra una destrucción o disposición de material.compliance:write
GET/compliance/reportsFilas ya formateadas de los reportes regulatorios.compliance:read

Incidencias

MétodoRutaQué haceAlcance
GET/incidentsIncidencias abiertas y cerradas del laboratorio.incidents:read
POST/incidentsReporta una incidencia.incidents:write
GET/incidents/{id}Detalle de una incidencia con su seguimiento.incidents:read
PATCH/incidents/{id}Actualiza el estado o los datos de una incidencia.incidents:write
POST/incidents/{id}/commentsAñade un comentario de seguimiento a una incidencia.incidents:write

Alertas

MétodoRutaQué haceAlcance
GET/alertsAlertas abiertas ordenadas por severidad.alerts:read
PATCH/alertsAtiende, asigna o cierra una alerta.alerts:write
GET/alerts/rulesReglas de generación de alertas configuradas.alerts:read
POST/alerts/rulesCrea una regla de alerta.alerts:write
GET/alerts/rules/{id}Detalle de una regla de alerta.alerts:read
PATCH/alerts/rules/{id}Actualiza una regla de alerta.alerts:write
DELETE/alerts/rules/{id}Elimina una regla de alerta.alerts:write

Educación

MétodoRutaQué haceAlcance
GET/education/practicesPrácticas de laboratorio programadas.education:read
POST/education/practicesPrograma una práctica de laboratorio.education:write
GET/education/practices/{id}Detalle de una práctica con sus recursos.education:read
PATCH/education/practices/{id}Actualiza una práctica.education:write
GET/education/reservationsReservas de recursos del laboratorio.education:read
POST/education/reservationsReserva un recurso para una práctica.education:write
GET/education/reservations/{id}Detalle de una reserva.education:read
PATCH/education/reservations/{id}Actualiza una reserva.education:write
DELETE/education/reservations/{id}Cancela una reserva.education:write
GET/education/groupsGrupos y secciones académicas.education:read
POST/education/groupsCrea un grupo académico.education:write

Investigación

MétodoRutaQué haceAlcance
GET/research/projectsProyectos de investigación.research:read
POST/research/projectsCrea un proyecto de investigación.research:write
GET/research/projects/{id}Detalle de un proyecto.research:read
PATCH/research/projects/{id}Actualiza un proyecto.research:write
GET/research/protocolsProtocolos y procedimientos normalizados.research:read
POST/research/protocolsCrea un protocolo.research:write
GET/research/protocols/{id}Detalle de un protocolo y su versión vigente.research:read
PATCH/research/protocols/{id}Actualiza un protocolo.research:write
GET/research/samplesMuestras de investigación con su trazabilidad.research:read
POST/research/samplesRegistra una muestra de investigación.research:write
GET/research/samples/{id}Detalle de una muestra de investigación.research:read
PATCH/research/samples/{id}Actualiza una muestra de investigación.research:write
GET/research/biobankAlícuotas y posiciones del biobanco.research:read
POST/research/biobankRegistra una alícuota en el biobanco.research:write
GET/research/biobank/{id}Detalle de una alícuota del biobanco.research:read
PATCH/research/biobank/{id}Actualiza una alícuota del biobanco.research:write
GET/research/notebooksCuadernos de laboratorio.research:read
POST/research/notebooksCrea un cuaderno de laboratorio.research:write
GET/research/notebooks/entriesEntradas de cuaderno de laboratorio.research:read
POST/research/notebooks/entriesAñade una entrada al cuaderno.research:write
GET/research/documentsRepositorio documental de investigación.research:read
POST/research/documentsRegistra un documento.research:write

Calidad

MétodoRutaQué haceAlcance
GET/quality/oosResultados fuera de especificación pendientes de investigación.quality:read

Bitácora

MétodoRutaQué haceAlcance
GET/auditBitácora de auditoría: quién hizo qué, cuándo y por qué.audit:read

Paginación

Añade limit (1-500, por omisión 100) y offset a cualquier colección. La respuesta incluye un objeto pagination con el total.

GET /api/v1/inventory/items?limit=50&offset=100

Límite de llamadas

Por omisión 120 por minuto y credencial, configurable al emitirla. Al superarlo se devuelve 429 con retryAfterSeconds.

Alcances

Un alcance de escritura incluye siempre su lectura. Pide lo mínimo: un ERP de compras normalmente solo necesita inventario, compras y catálogo.

AlcanceQué permite
inventory:readLeer inventario y existencias
inventory:writeCrear artículos y registrar movimientos
equipment:readLeer equipos, planes y eventos
equipment:writeCrear y actualizar equipos y mantenimientos
specimens:readLeer muestras
specimens:writeRecibir muestras y cambiar su estado
results:readLeer resultados
results:writeRegistrar resultados
results:approveAprobar resultados
purchasing:readLeer solicitudes de compra
purchasing:writeCrear y actualizar solicitudes de compra
compliance:readLeer cumplimiento, licencias y permisos
compliance:writeRegistrar recepciones, conteos y destrucciones
incidents:readLeer incidencias
incidents:writeCrear y gestionar incidencias
alerts:readLeer alertas
alerts:writeAtender alertas y reglas
education:readLeer prácticas y reservas
education:writeGestionar prácticas y reservas
research:readLeer proyectos, protocolos y biobancos
research:writeGestionar proyectos, muestras y cuadernos
quality:readLeer calidad y desviaciones
quality:writeGestionar calidad
audit:readConsultar la bitácora
catalog:readLeer catálogos y datos maestros

Webhooks

Un administrador los registra en Integraciones → Webhooks, indicando la URL de destino (HTTPS obligatorio) y los eventos. Se admiten comodines: * para todo, INVENTORY_* para un módulo entero, o el nombre exacto de una acción.

Forma del envío

POST https://tu-erp.institucion.com/hooks/nexalab
Content-Type: application/json
x-nexalab-event: INVENTORY_ITEM_CREATED
x-nexalab-delivery: 6f1c…
x-nexalab-timestamp: 1753900000
x-nexalab-signature: v1=<hmac-sha256-hex>

{
  "id": "…",
  "type": "INVENTORY_ITEM_CREATED",
  "createdAt": "2026-07-30T18:22:11.000Z",
  "data": { "action": "…", "entityId": "…", "newValue": { … } }
}

Verifica la firma siempre

Calcula el HMAC sobre el cuerpo crudo, antes de parsear el JSON, y compara con tiempo constante.

const esperado = "v1=" + crypto
  .createHmac("sha256", SECRETO)
  .update(`${headers["x-nexalab-timestamp"]}.${cuerpoCrudo}`)
  .digest("hex");

Reintentos e idempotencia

Si no respondes 2xx, NexaLab reintenta hasta 5 veces con espera creciente (1, 5, 15 y 60 minutos). El campo id es estable entre reintentos: úsalo para descartar duplicados. Responde 2xx en cuanto recibas el evento y procésalo después; si tardas más de 10 segundos, el envío se da por fallido.

Errores

Siempre con la forma { "error": "<código>", "message": "<explicación>" }.

CódigoHTTPSignificado
missing_credentials401No se envió credencial
invalid_credentials401Clave o token inválido
revoked / expired403Credencial revocada o vencida
actor_without_access403El usuario responsable ya no tiene acceso al laboratorio
insufficient_scope403Falta el alcance; la respuesta dice cuál
rate_limited429Se superó el límite por minuto
not_found404La ruta no existe en la API
invalid_json400El cuerpo no es JSON válido

Los errores de validación de negocio llegan tal cual del módulo, con message e issues señalando exactamente qué campo falta.

Cada respuesta lleva x-nexalab-request-id. Cítalo al reportar un problema: la llamada queda registrada con su duración y su resultado.

Guías por plataforma

Power Apps y Power Automate

  1. Descarga el archivo del conector.
  2. En Power Apps: Conectores personalizados → Nuevo conector → Importar un archivo OpenAPI.
  3. En Seguridad, elige Clave de API, parámetro X-API-Key, ubicación Encabezado.
  4. Crea la conexión pegando la clave emitida en NexaLab.

Se publica en Swagger 2.0 porque es el único formato que acepta ese importador. Para todo lo demás, usa el OpenAPI 3.1.

SAP

Usa el flujo OAuth2 client_credentials contra /api/v1/oauth/token. Registra el destino con la URL base https://nexalaboratories.com/api/v1 y renueva el token cuando expire. Para el sentido contrario, registra un webhook apuntando al endpoint de tu middleware.

Cualquier otro ERP o desarrollo propio

Envía X-API-Key en cada llamada y genera el cliente desde el spec OpenAPI. Ejemplo de sincronización de existencias:

BASE="https://nexalaboratories.com/api/v1"
CLAVE="nxk_live_…"

# Traer el inventario
curl -H "X-API-Key: $CLAVE" "$BASE/inventory/items?limit=200"

# Registrar una entrada tras recibir una compra
curl -X POST "$BASE/inventory/movements" \
  -H "X-API-Key: $CLAVE" -H "Content-Type: application/json" \
  -d '{"inventoryItemId":"<uuid>","movementType":"IN","quantity":10,"reason":"Recepción OC-4471"}'

¿Necesitas una credencial?

Las emite un administrador del laboratorio desde el módulo Integraciones. Si eres proveedor externo, pídesela a tu contacto en la institución indicando qué alcances necesitas y para qué.