Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card
Monitorización remota de pacientes con FHIR
Desde lecturas de presión arterial en casa hasta alertas: Observaciones de dispositivos, webhooks firmados, una regla idempotente y lo que queda fuera de la capa de datos. Código probado.
La monitorización remota de pacientes (RPM) recopila mediciones que un paciente realiza en casa —presión arterial, peso, glucosa, saturación de oxígeno— y permite a un equipo de atención verlas y actuar sobre ellas entre visitas. La parte de los datos consta de cuatro pasos: introducir cada lectura en el registro del paciente como una Observación codificada y atribuida al dispositivo; reaccionar cuando llega una nueva lectura; decidir con una regla clara si necesita atención; y mantener un registro de lo que hizo el equipo. Esta página construye esa canalización sobre HL7 FHIR R4 con webhooks de Anpheros y el SDK de TypeScript, con código que se ejecutó contra la plataforma, y enumera lo que queda fuera de la capa de datos.
El pipeline
cuff, scale, glucose meter, pulse oximeter
│ (Bluetooth / vendor app / Apple Health / Health Connect)
▼
patient's phone app ──► your backend ──► FHIR Observation (author: device) in the patient's record
│ webhook: resource.created (signed)
▼
your monitoring service: rule → alert → care team
│
note, call, CarePlan change, next appointment
Tres opciones deciden si esto funciona en la práctica:
- Una lectura, una Observation. Cada lectura del manguito es una Observation con LOINC 85354-9 y dos componentes (8480-6 sistólica, 8462-4 diastólica), la hora de la medición y
author_type: device. A diferencia de los resúmenes diarios de dispositivos portátiles, las lecturas de RPM son mediciones individuales que un clínico puede examinar una por una. - Reaccionar a eventos, no a un temporizador. Un webhook por cada nueva Observation permite que la regla se ejecute segundos después de que llegue la lectura.
- Reglas sobre varias lecturas. Una sola lectura alta suele ser ruido; la mayoría de los protocolos analizan una serie. La regla a continuación solicita tres lecturas consecutivas en o por encima de 140/90. Ese umbral es un ejemplo, no un consejo clínico: el equipo de atención establece la regla para cada paciente.
Escribir lecturas desde el dispositivo
La aplicación del teléfono (o la nube del proveedor del dispositivo, a través de su backend) escribe cada lectura:
await anpheros.observations.create(patientId, {
code: '85354-9', category: 'vital-signs', effective_at: '2026-10-13T07:15:00-04:00', author_type: 'device',
components: [{ code: '8480-6', value: 152, unit: 'mm[Hg]' }, { code: '8462-4', value: 95, unit: 'mm[Hg]' }],
}, { source_system: 'bp-cuff-app' });
Si las lecturas provienen de Apple Health o Health Connect en lugar de directamente del dispositivo, léalas en el teléfono como se describe en Datos de wearables en FHIR, pero mantenga las lecturas individuales de presión arterial como Observaciones individuales en lugar de promedios diarios.
Reaccionar a nuevas lecturas
Registre un endpoint de webhook una vez (POST /v1/webhooks con events: ["resource.created"]); la respuesta contiene el secreto de firma. Luego, ejecute un pequeño servicio que verifique cada entrega y evalúe la regla:
import { createServer } from 'node:http';
import { Anpheros, apiKey, verifyWebhookSignature } from '@anpheros/sdk';
const anpheros = new Anpheros({ auth: apiKey(process.env.ANPHEROS_KEY!) });
const SECRET = process.env.WEBHOOK_SECRET!;
const seen = new Set<string>(); // deliveries are at-least-once: de-duplicate by event id
const alerted = new Set<string>(); // one alert per newest reading, however many events arrive
// Rule: the three most recent home readings all at or above 140/90 → tell the care team once
async function checkBloodPressure(patientId: string, observationId: string) {
const obs = await anpheros.observations.get(observationId);
if (obs.code !== '85354-9') return; // only blood pressure readings trigger the rule
const { data } = await anpheros.observations.list(patientId, { code: '85354-9', limit: 3 }); // newest first
const value = (o: typeof obs, code: string) => o.components.find(c => c.code === code)?.value ?? 0;
const allHigh = data.length === 3 && data.every(o => value(o, '8480-6') >= 140 || value(o, '8462-4') >= 90);
if (!allHigh || alerted.has(data[0].id)) return;
alerted.add(data[0].id);
console.log(`ALERT patient ${patientId}: last 3 readings ≥ 140/90 →`,
data.map(o => `${value(o, '8480-6')}/${value(o, '8462-4')}`).join(', ')); // in production: notify the care team
}
createServer(async (req, res) => {
const chunks: Buffer[] = [];
for await (const c of req) chunks.push(c as Buffer);
const body = Buffer.concat(chunks).toString('utf8');
const ok = await verifyWebhookSignature({ secret: SECRET, header: req.headers['anpheros-signature'] as string, body });
if (!ok) { res.writeHead(400).end(); return; } // not from Anpheros, or too old
res.writeHead(204).end(); // answer fast; do the work after
const event = JSON.parse(body);
if (seen.has(event.id)) return;
seen.add(event.id);
const d = event.data;
if (event.type === 'resource.created' && d.resource_type === 'Observation') await checkBloodPressure(d.patient, d.id);
}).listen(8799);
Cómo lo probamos: cuatro lecturas matutinas (136/86, 144/92, 149/94, 152/95) se escribieron en un paciente sintético en una instancia local de la plataforma, y la plataforma produjo un evento resource.created firmado por lectura. Esos eventos, firmados con el propio código de firma de la plataforma, se enviaron al servicio anterior junto con dos duplicados y una solicitud firmada con un secreto incorrecto. El resultado: la firma incorrecta obtuvo 400, los duplicados se ignoraron y el servicio generó exactamente una alerta — 152/95, 149/94, 144/92 — no una por evento.
En producción, mantenga seen y alerted en una base de datos en lugar de en memoria, para que un reinicio no repita las alertas.
Recibir webhooks durante el desarrollo. Anpheros acepta y entrega solo a endpoints HTTPS públicos: una dirección localhost o privada es rechazada cuando la registra (400, campo url), incluso en el sandbox, y cada entrega verifica la dirección nuevamente. Para recibir eventos en su portátil, exponga el servicio a través de un túnel HTTPS público y registre la dirección del túnel. Consulte Webhooks.
Lo que el registro debería mostrar después
La alerta en sí reside en su servicio de monitoreo, pero el registro debería mostrar el resultado de la misma, para que el próximo clínico y el paciente vean la historia completa:
- las lecturas, cada una marcada como datos del dispositivo con su sistema de origen (procedencia);
- un
CarePlancon el plan de monitoreo (qué se mide, con qué frecuencia, el objetivo); - un
Encounter(claseVRpara un contacto remoto) cuando el equipo llama al paciente, y cualquier cambio de medicación como unMedicationStatement.
Anpheros almacena estos recursos; no tiene un recurso de alerta o tarea propio (Flag, Task y Communication no se encuentran entre sus tipos de recursos), por lo que las colas de alertas y el enrutamiento de guardias pertenecen a su servicio.
Facturación, regulación y seguridad
Los programas de RPM a menudo dependen de las reglas de reembolso. En los Estados Unidos, Medicare paga por la monitorización fisiológica remota bajo códigos CPT específicos con un número mínimo de días con datos y tiempo dedicado por el equipo de atención. Esas reglas cambian y no son algo que una plataforma de datos pueda certificar; consulte las reglas actuales de CMS y conserve la evidencia (las lecturas y el tiempo del equipo) en su propio sistema. El software que interpreta las lecturas para impulsar el diagnóstico o el tratamiento puede estar regulado como un dispositivo médico. Mantenga los umbrales en manos de los clínicos y registre cada alerta y respuesta.
Dónde encaja Anpheros
Anpheros proporciona el registro (FHIR R4 Observations con procedencia, CarePlan, Encounter), webhooks firmados con reintentos, consentimiento si la aplicación de otra organización necesita leer las lecturas, y un registro de acceso que el paciente puede ver. No se conecta a los proveedores de dispositivos, no decide qué es anormal, no envía alertas ni gestiona la facturación.
Preguntas frecuentes
¿Qué recurso FHIR almacena una lectura de presión arterial en casa?
Una Observation con LOINC 85354-9 (panel de presión arterial) y dos componentes, 8480-6 (sistólica) y 8462-4 (diastólica), cada una una valueQuantity en mm[Hg], con la hora de la medición y el dispositivo como autor.
¿Deben los datos de RPM ser promedios diarios o lecturas individuales?
Lecturas individuales para mediciones clínicas como presión arterial, peso o glucosa, ya que los clínicos las revisan y cuentan. Los resúmenes diarios son adecuados para datos de alta frecuencia de dispositivos portátiles como la frecuencia cardíaca o los pasos.
¿Cómo activo una alerta cuando llega una nueva lectura?
Suscríbase a los webhooks de resource.created, verifique la firma, obtenga la nueva Observation y evalúe su regla sobre la serie reciente. Las entregas pueden repetirse, así que elimine duplicados por ID de evento y haga que la alerta sea idempotente.
¿Puede Anpheros enviar alertas a los médicos?
No. Notifica a su servicio a través de webhooks; quién es alertado, cómo y cuándo se decide en su sistema.
Relacionado
- Datos de wearables en FHIR
- Atención virtual y médicos IA: los datos que necesitan
- Webhooks
- Explicación de la procedencia de los datos médicos
- Integraciones de atención médica
Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card