Luna Health API — Referencia de la API
Introducción
Luna Health ofrece una API REST moderna que le permite integrarse con nuestra plataforma de forma programática.
Para Desarrolladores
- Tiene acceso programático a las mismas funcionalidades disponibles en la plataforma Luna Health
- Cree sus propias representaciones de datos personalizadas y herramientas de informes
- Nuestro equipo de soporte para desarrolladores está disponible para ayudarle a integrarse con nuestra plataforma
Descripción General de la API
Nuestra API se adhiere a los principios REST y está diseñada para ser amigable para los desarrolladores. Utiliza métodos HTTP estándar y devuelve respuestas en formato JSON.
Autenticación
El acceso a la API requiere autenticación mediante claves API. Debe incluir su clave API en el encabezado de Autorización de todas las solicitudes utilizando el formato de token Bearer:
Authorization: Bearer SU_CLAVE_API_AQUÍAdvertencia de Seguridad
Nunca comparta sus claves API en áreas de acceso público como GitHub, código del lado del cliente, etc. Las claves API deben almacenarse de forma segura en el servidor.
Generación de Claves API
Puede generar y administrar claves API en la configuración de su cuenta de Luna Health. Siga estos pasos:
1. Inicie sesión en su cuenta de Luna Health 2. Navegue a Configuración > Claves API 3. Haga clic en "Generar Nueva Clave API" 4. Almacene su nueva clave API de forma segura, ya que solo se mostrará una vez
Manejo de Errores
Todos los errores se devuelven en un formato consistente con códigos de estado HTTP apropiados.
Biomarcadores
Endpoints relacionados con biomarcadores
Pacientes
Endpoints relacionados con pacientes
- GETListar pacientes
/patients - POSTCreate a patient
/patients - GETObtener paciente por id
/patient - PATCHUpdate a patient’s contact information
/patients/{id} - GETObtener notas clínicas del paciente
/patient-charts - GETListar los formularios completados de un paciente
/patient-forms - GETObtener un formulario completado de un paciente
/patient-form - GETDescargar un formulario completado en PDF
/patient-form/pdf
Webhooks
Endpoint de solo lectura para recuperar la configuración de webhook de su organización. La clave secreta nunca se devuelve y los ajustes de webhook se modifican desde la configuración de su cuenta de Luna Health, no a través de la API pública. Actualmente Luna Health envía cinco eventos de pruebas de laboratorio — lab_test.processed, lab_test.failed, lab_test.rejected, lab_test.split y lab_test.split_error —, form.completed y cuatro eventos de citas — appointment.created, appointment.updated, appointment.cancelled y appointment.no_show — como solicitudes POST firmadas a la URL que configure.
Eventos que enviamos
lab_test.processed— una prueba de laboratorio terminó de procesarse y se extrajeron sus biomarcadores.datasiempre incluyelab_test_id,patient_id,status,biomarker_countytimestamp. También puede incluirimageset_idysubmission_id: solo se envían para pruebas de laboratorio digitalizadas a partir de un conjunto de imágenes.lab_test.failed— una prueba de laboratorio no pudo procesarse.datasiempre incluyeerrorytimestamp. También puede incluirlab_test_id,patient_id,imageset_idysubmission_id:lab_test_idypatient_idse omiten cuando la falla ocurre antes de identificar la prueba de laboratorio o su paciente, y los campos del conjunto de imágenes solo se envían para cargas digitalizadas.lab_test.rejected— un conjunto de imágenes enviado fue rechazado durante la digitalización.datasiempre incluyeimageset_id,rejection_commentytimestamp. También puede incluirrejection_reason_id,lab_test_id,patient_idyerror:rejection_reason_idse omite cuando el servicio de digitalización no indica un código de motivo, y cuando el conjunto de imágenes rechazado no puede asociarse a una prueba de laboratorio, se omitenlab_test_idypatient_idyerrorexplica el motivo.lab_test.split— un conjunto de imágenes enviado se dividió en pruebas de laboratorio separadas.datasiempre incluyeimageset_id,patient_id,sub_file_idytimestamp. También puede incluirlab_test_id: se omite mientras el archivo dividido aún no está vinculado a una prueba de laboratorio.lab_test.split_error— no se pudo completar la división de un conjunto de imágenes.datasiempre incluyeimageset_id,errorytimestamp.form.completed— un paciente completó un formulario, como un formato de ingreso, admisión o consentimiento. Las respuestas no vienen en el evento: léalas conGET /patient-form?id=usandoform_id. Solo se envía sisend_form_updatesestá activado.datasiempre incluyeform_id,patient_idycompleted_at.appointment.created— se agendó una cita, desde el panel, su página de reservas, el asistente virtual oPOST /appointments. Una nueva serie recurrente envía un evento por cada cita de la serie.statuses PENDING cuando la clínica aún debe aprobar la solicitud del paciente. Solo se envía sisend_appointment_updatesestá activado, como todos los eventosappointment.datasiempre incluyeappointment_id,patient_id,staff_ids,service_id,location_id,status,start_timeyend_time.appointment.updated— una cita cambió de horario, se asignó a otros profesionales de salud, o ambas cosas.changesindicastart_timey/ostaff.previous_start_timeyprevious_staff_idscontienen los valores anteriores al cambio, y son null cuando el canal que hizo el cambio no los reportó.datasiempre incluyeappointment_id,patient_id,staff_ids,service_id,location_id,status,start_time,end_time,changes,previous_start_timeyprevious_staff_ids.appointment.cancelled— se canceló una cita, por la clínica, por el paciente o mediantePOST /appointments/{id}/cancel.datasiempre incluyeappointment_id,patient_id,staff_ids,service_id,location_id,status,start_timeyend_time.appointment.no_show— una cita pendiente o confirmada se marcó como inasistencia, desde el panel o mediantePOST /appointments/{id}/no-show.datasiempre incluyeappointment_id,patient_id,staff_ids,service_id,location_id,status,start_timeyend_time.
También se entrega un evento test cuando usa el botón de prueba en la configuración de su cuenta, para confirmar que su endpoint funciona antes de habilitarlo.
Los indicadores devueltos por este endpoint controlan la entrega: enabled activa o desactiva el webhook para toda la organización, send_lab_test_updates controla los eventos lab_test anteriores, send_form_updates controla form.completed y send_appointment_updates controla los eventos appointment. Cada familia de eventos está desactivada hasta que la active en la configuración de su cuenta. send_biomarker_updates está reservado para una futura familia de eventos biomarker; hoy no se envía ningún evento de biomarcadores.
Ignore cualquier tipo de evento que no reconozca: podemos agregar nuevos tipos de evento, y siempre llegan desactivados para un webhook existente hasta que los active.
Cada formulario completado se anuncia una sola vez, aunque el paciente lo envíe dos veces. Aun así, trate la entrega como al menos una vez y use los identificadores de data (como form_id, lab_test_id o appointment_id) para ignorar cualquier evento que ya haya procesado. Los eventos de citas reportan cambios hechos por cualquier canal, incluidas sus propias llamadas a la API, así que compare appointment_id con los cambios que su integración acaba de hacer para no procesarlos dos veces.
Estructura de la carga útil
Cada entrega es una solicitud HTTP POST con Content-Type: application/json y el mismo sobre. Solo data varía según el evento:
{
"event": "lab_test.processed",
"timestamp": "2025-01-01T00:00:00.000Z",
"organization_id": "6543210fedcba9876543210f",
"data": {
"lab_test_id": "6543210fedcba9876543210a",
"patient_id": "6543210fedcba9876543210b",
"status": "COMPLETED",
"biomarker_count": 42,
"timestamp": "2025-01-01T00:00:00.000Z"
}
}Una entrega de form.completed solo incluye el formulario, el paciente y cuándo se completó el formulario:
{
"event": "form.completed",
"timestamp": "2025-01-01T00:00:05.000Z",
"organization_id": "6543210fedcba9876543210f",
"data": {
"form_id": "6543210fedcba9876543210c",
"patient_id": "6543210fedcba9876543210b",
"completed_at": "2025-01-01T00:00:00.000Z"
}
}Una entrega de appointment.updated para una cita que se movió a otra hora y a otro profesional de salud:
{
"event": "appointment.updated",
"timestamp": "2025-01-02T15:00:01.000Z",
"organization_id": "6543210fedcba9876543210f",
"data": {
"appointment_id": "6543210fedcba9876543210d",
"patient_id": "6543210fedcba9876543210b",
"staff_ids": ["6543210fedcba98765432101"],
"service_id": "6543210fedcba98765432102",
"location_id": null,
"status": "CONFIRMED",
"start_time": "2025-01-03T17:00:00.000Z",
"end_time": "2025-01-03T17:50:00.000Z",
"changes": ["start_time", "staff"],
"previous_start_time": "2025-01-03T16:00:00.000Z",
"previous_staff_ids": ["6543210fedcba98765432103"]
}
}Los eventos contienen identificadores, no valores clínicos. Use esos identificadores para leer los registros desde los endpoints de Pruebas de Laboratorio y Biomarcadores, las respuestas de un formulario completado desde GET /patient-form y una cita desde GET /appointments.
Cómo verificar una entrega
Cada solicitud incluye el encabezado X-Luna-Signature: el HMAC-SHA256 del cuerpo original de la solicitud, firmado con su clave secreta de webhook y codificado en hexadecimal. Vuelva a calcular el HMAC sobre los bytes exactos que recibió y compárelo con una comparación de tiempo constante antes de confiar en la carga útil. Rechace cualquier solicitud cuya firma no coincida.
Comportamiento de entrega
Cada evento se intenta una sola vez, con un tiempo de espera de 10 segundos, y no se reintenta automáticamente. Responda 2xx con prontitud y realice el trabajo lento fuera de la solicitud para no perder una entrega por tiempo de espera. Como no hay reintentos, concilie con los endpoints de lectura si su integración necesita una garantía de completitud.
Su endpoint debe ser una dirección HTTPS pública. Se rechaza http:// sin cifrar, así como las direcciones internas, privadas y de loopback —incluidos los nombres de host que resuelvan a una de ellas—, porque las entregas contienen identificadores vinculados a pacientes.
Pruebas de Laboratorio
Endpoints relacionados con pruebas de laboratorio
Etiquetas de Pacientes
Endpoints para consultar las etiquetas de pacientes de su organización y para asignarlas o quitarlas a un paciente. Las etiquetas son solo rótulos: no permiten escribir datos clínicos ni de contacto, y tanto el paciente como la etiqueta están acotados a su organización. Asignar o quitar etiquetas requiere una clave de API con permiso de escritura.
Citas
Endpoints para listar y gestionar citas de su organización, y para consultar los profesionales de salud, servicios y horarios disponibles para agendar
- GETListar citas
/appointments - POSTCrear una cita
/appointments - GETObtener horarios disponibles
/availability - GETObtener horarios disponibles en un rango de fechas
/availability/range - POSTCancelar una cita
/appointments/{id}/cancel - POSTMarcar una cita como inasistencia
/appointments/{id}/no-show - POSTReagendar una cita
/appointments/{id}/reschedule - GETListar servicios
/services - GETListar profesionales de salud
/staff
Pagos
Endpoints para recuperar registros de pagos (facturas) de su organización: listar pagos con filtrado por estado, método de pago, paciente y rango de fechas, y consultar un pago individual por ID. De la factura (CFDI) solo se exponen su UUID del SAT, serie, folio, estado y fechas de timbrado o cancelación; nunca los datos fiscales del receptor ni del emisor, los archivos XML/PDF ni identificadores de Stripe.