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
- Pide la credencial. La emite un administrador del laboratorio desde Integraciones → Credenciales. Recibirás un
client_idy una clave secreta que solo se muestra una vez. - 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. - 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/meAutenticació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.
- Una credencial pertenece a un laboratorio. Una institución con tres laboratorios emite tres credenciales. El alcance nunca es ambiguo.
- 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:writea una credencial cuyo responsable solo puede leer inventario no habilita nada. - 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étodo | Ruta | Qué hace | Alcance |
|---|---|---|---|
| GET | /inventory/items | Lista los artículos de inventario activos con existencia, lote y vencimiento. | inventory:read |
| POST | /inventory/items | Da 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}/discard | Registra la baja o descarte de un artículo de inventario. | inventory:write |
| GET | /inventory/movements | Kardex de movimientos de existencia (solo anexado). | inventory:read |
| POST | /inventory/movements | Registra una entrada, salida o ajuste de existencia. | inventory:write |
| GET | /inventory/controlled | Artículos marcados como reactivo controlado, de doble uso o precursor. | inventory:read |
| GET | /inventory/controlled/requests | Solicitudes de autorización de uso de reactivo controlado. | inventory:read |
| POST | /inventory/controlled/requests | Crea 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étodo | Ruta | Qué hace | Alcance |
|---|---|---|---|
| GET | /inventory/categories | Categorías de inventario, para mapear contra las del ERP. | catalog:read |
| POST | /inventory/categories | Crea una categoría de inventario. | inventory:write |
| PATCH | /inventory/categories | Actualiza una categoría de inventario. | inventory:write |
| GET | /locations | Ubicaciones de almacenamiento del laboratorio. | catalog:read |
| POST | /locations | Crea una ubicación de almacenamiento. | inventory:write |
Equipos
| Método | Ruta | Qué hace | Alcance |
|---|---|---|---|
| GET | /equipment | Equipos del laboratorio con estado, calibración y próximo mantenimiento. | equipment:read |
| POST | /equipment | Da 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/events | Eventos de equipo: calibraciones, mantenimientos y verificaciones. | equipment:read |
| POST | /equipment/events | Registra un evento de calibración o mantenimiento. | equipment:write |
| GET | /equipment/plans | Planes de mantenimiento y calibración programados. | equipment:read |
| POST | /equipment/plans | Crea 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/certificates | Certificados de calibración registrados. | equipment:read |
| POST | /equipment/certificates | Registra un certificado de calibración. | equipment:write |
Muestras
| Método | Ruta | Qué hace | Alcance |
|---|---|---|---|
| GET | /specimens | Muestras recibidas con su estado en el flujo de trabajo. | specimens:read |
| POST | /specimens | Recibe una muestra y genera su número de acceso. | specimens:write |
| POST | /specimens/{id}/transitions | Mueve una muestra al siguiente estado del flujo configurado. | specimens:write |
Resultados
| Método | Ruta | Qué hace | Alcance |
|---|---|---|---|
| GET | /results | Resultados registrados con su método, versión y estado. | results:read |
| POST | /results | Registra un resultado analítico. | results:write |
Compras
| Método | Ruta | Qué hace | Alcance |
|---|---|---|---|
| GET | /purchasing/requests | Solicitudes de compra con su estado de aprobación. | purchasing:read |
| POST | /purchasing/requests | Crea 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étodo | Ruta | Qué hace | Alcance |
|---|---|---|---|
| GET | /compliance | Resumen del estado de cumplimiento del laboratorio. | compliance:read |
| GET | /compliance/catalog | Catálogo de sustancias con CAS, clasificación y requisitos. | compliance:read |
| POST | /compliance/catalog | Añ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/permits | Licencias y permisos vigentes del laboratorio. | compliance:read |
| POST | /compliance/permits | Registra una licencia o permiso. | compliance:write |
| PATCH | /compliance/permits | Actualiza una licencia o permiso. | compliance:write |
| GET | /compliance/receipts | Recepciones con factura, orden de compra, licencia y permiso. | compliance:read |
| POST | /compliance/receipts | Registra la recepción documentada de material controlado. | compliance:write |
| GET | /compliance/counts | Conteos físicos de existencia realizados. | compliance:read |
| POST | /compliance/counts | Abre 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/disposals | Destrucciones y disposiciones registradas. | compliance:read |
| POST | /compliance/disposals | Registra una destrucción o disposición de material. | compliance:write |
| GET | /compliance/reports | Filas ya formateadas de los reportes regulatorios. | compliance:read |
Incidencias
| Método | Ruta | Qué hace | Alcance |
|---|---|---|---|
| GET | /incidents | Incidencias abiertas y cerradas del laboratorio. | incidents:read |
| POST | /incidents | Reporta 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}/comments | Añade un comentario de seguimiento a una incidencia. | incidents:write |
Alertas
| Método | Ruta | Qué hace | Alcance |
|---|---|---|---|
| GET | /alerts | Alertas abiertas ordenadas por severidad. | alerts:read |
| PATCH | /alerts | Atiende, asigna o cierra una alerta. | alerts:write |
| GET | /alerts/rules | Reglas de generación de alertas configuradas. | alerts:read |
| POST | /alerts/rules | Crea 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étodo | Ruta | Qué hace | Alcance |
|---|---|---|---|
| GET | /education/practices | Prácticas de laboratorio programadas. | education:read |
| POST | /education/practices | Programa 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/reservations | Reservas de recursos del laboratorio. | education:read |
| POST | /education/reservations | Reserva 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/groups | Grupos y secciones académicas. | education:read |
| POST | /education/groups | Crea un grupo académico. | education:write |
Investigación
| Método | Ruta | Qué hace | Alcance |
|---|---|---|---|
| GET | /research/projects | Proyectos de investigación. | research:read |
| POST | /research/projects | Crea 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/protocols | Protocolos y procedimientos normalizados. | research:read |
| POST | /research/protocols | Crea 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/samples | Muestras de investigación con su trazabilidad. | research:read |
| POST | /research/samples | Registra 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/biobank | Alícuotas y posiciones del biobanco. | research:read |
| POST | /research/biobank | Registra 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/notebooks | Cuadernos de laboratorio. | research:read |
| POST | /research/notebooks | Crea un cuaderno de laboratorio. | research:write |
| GET | /research/notebooks/entries | Entradas de cuaderno de laboratorio. | research:read |
| POST | /research/notebooks/entries | Añade una entrada al cuaderno. | research:write |
| GET | /research/documents | Repositorio documental de investigación. | research:read |
| POST | /research/documents | Registra un documento. | research:write |
Calidad
| Método | Ruta | Qué hace | Alcance |
|---|---|---|---|
| GET | /quality/oos | Resultados fuera de especificación pendientes de investigación. | quality:read |
Bitácora
| Método | Ruta | Qué hace | Alcance |
|---|---|---|---|
| GET | /audit | Bitá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=100Lí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.
| Alcance | Qué permite |
|---|---|
inventory:read | Leer inventario y existencias |
inventory:write | Crear artículos y registrar movimientos |
equipment:read | Leer equipos, planes y eventos |
equipment:write | Crear y actualizar equipos y mantenimientos |
specimens:read | Leer muestras |
specimens:write | Recibir muestras y cambiar su estado |
results:read | Leer resultados |
results:write | Registrar resultados |
results:approve | Aprobar resultados |
purchasing:read | Leer solicitudes de compra |
purchasing:write | Crear y actualizar solicitudes de compra |
compliance:read | Leer cumplimiento, licencias y permisos |
compliance:write | Registrar recepciones, conteos y destrucciones |
incidents:read | Leer incidencias |
incidents:write | Crear y gestionar incidencias |
alerts:read | Leer alertas |
alerts:write | Atender alertas y reglas |
education:read | Leer prácticas y reservas |
education:write | Gestionar prácticas y reservas |
research:read | Leer proyectos, protocolos y biobancos |
research:write | Gestionar proyectos, muestras y cuadernos |
quality:read | Leer calidad y desviaciones |
quality:write | Gestionar calidad |
audit:read | Consultar la bitácora |
catalog:read | Leer 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ódigo | HTTP | Significado |
|---|---|---|
missing_credentials | 401 | No se envió credencial |
invalid_credentials | 401 | Clave o token inválido |
revoked / expired | 403 | Credencial revocada o vencida |
actor_without_access | 403 | El usuario responsable ya no tiene acceso al laboratorio |
insufficient_scope | 403 | Falta el alcance; la respuesta dice cuál |
rate_limited | 429 | Se superó el límite por minuto |
not_found | 404 | La ruta no existe en la API |
invalid_json | 400 | El 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
- Descarga el archivo del conector.
- En Power Apps: Conectores personalizados → Nuevo conector → Importar un archivo OpenAPI.
- En Seguridad, elige Clave de API, parámetro
X-API-Key, ubicación Encabezado. - 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é.
