Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card
Egészségügyi API építése TypeScript-tel
Oktatóanyag: egy Express API TypeScriptben, amely betegrekordokat hoz létre, vérnyomásértékeket tárol FHIR R4 megfigyelésekként, visszaolvassa őket, kezeli a hibákat és ellenőrzi a webhookokat – saját orvosi adatbázis nélkül.
Ez az oktatóanyag egy vérnyomáskövető alkalmazás backend API-ját építi fel TypeScript-ben és Express-szel: a regisztráció létrehozza a felhasználó orvosi rekordját, az értékeket kódolt HL7 FHIR R4 megfigyelésekként tároljuk, az alkalmazás visszaolvassa őket, és egy webhook végpont értesül az új adatokról, mindezt saját orvosi adatbázis nélkül. Az API megtartja a termék specifikus elemeit (felhasználók, munkamenetek, beállítások). Az orvosi adatok, azok története, hozzájárulása és eredete az Anpheros-ban él, amelyet a TypeScript SDK segítségével hívhat meg.
Architektúra
mobile / web app ──► your API (Express, TypeScript) ──► Anpheros (FHIR R4 record per patient)
│ users, sessions, settings │ observations, conditions, documents,
│ user id → patient id │ provenance, consent, audit
◄──────────── webhooks ──────────────┘
Az Ön adatbázisa minden felhasználóhoz egy extra oszlopot tárol: az Anpheros betegazonosítójukat. Minden klinikai adat az API-n keresztül halad, így az kódolt, verziózott és bármely FHIR rendszer vagy a beteg beleegyezésével rendelkező egyéb alkalmazások által olvasható. Orvosi alkalmazás backend és adatbázis részletesen elmagyarázza a felosztást.
Kezdés előtt
- Node.js 18 vagy újabb verzió.
- Egy sandbox kulcs (
sk_test_…) a platform.anpheros.com/dashboard webhelyről (Szerezz be egy sandbox kulcsot). Tartsd azt kizárólag a szerveren; soha ne juttasd el az alkalmazásba.
mkdir bp-api && cd bp-api
npm init -y && npm pkg set type=module
npm install express @anpheros/sdk
npm install -D typescript tsx @types/express @types/node
export ANPHEROS_KEY=sk_test_…
1. lépés: Az ügyfél és a felhasználói tároló
// server.ts
import express from 'express';
import { Anpheros, AnpherosError, apiKey, verifyWebhookSignature } from '@anpheros/sdk';
const anpheros = new Anpheros({ auth: apiKey(process.env.ANPHEROS_KEY!) });
const app = express();
// Your own user table. In production this is your database; the only medical link is patientId.
type User = { id: string; email: string; patientId: string };
const users = new Map<string, User>();
// Stand-in for your real authentication (session cookie, JWT…): it must set the signed-in user.
function currentUser(req: express.Request): User {
const user = users.get(req.header('x-user-id') ?? '');
if (!user) throw new HttpError(401, 'not signed in');
return user;
}
class HttpError extends Error {
constructor(readonly status: number, message: string) { super(message); }
}
2. lépés: A regisztráció létrehozza az orvosi nyilvántartást
Amikor valaki regisztrál, hozza létre a páciensét az Anpheros-ban, és tegye a saját felhasználói azonosítóját a identifiers mezőbe, így a nyilvántartás mindig megtalálható lesz az Ön oldaláról:
app.post('/signup', express.json(), async (req, res, next) => {
try {
const { email, given, family, birthDate } = req.body;
const userId = crypto.randomUUID();
const patient = await anpheros.patients.create(
{ given, family, birth_date: birthDate, identifiers: [{ system: 'https://bp.example/user', value: userId }] },
{ author_type: 'patient' },
);
users.set(userId, { id: userId, email, patientId: patient.id });
res.status(201).json({ userId });
} catch (e) { next(e); }
});
Az Anpheros válasza az új páciens, amely tartalmazza a projektjéhez tartozó id azonosítót és annak FHIR referenciáját:
{"id": "27296656-c2ba-4970-8424-1dcd91163e0a", "given": "Ioana", "family": "Marin", "birth_date": "1979-04-12", "gender": "female",
"identifiers": [{"system": "https://bp.example/user", "value": "u_8f2c"}], "updated_at": "2026-10-12T20:16:51.143Z",
"fhir": "Patient/27296656-c2ba-4970-8424-1dcd91163e0a"}
3. lépés: mérés tárolása
Az alkalmazás elküldi a {systolic, diastolic, measuredAt}. Az Ön API-ja érvényesíti azt, és eltárolja az egyik vérnyomás-megfigyelést, LOINC 85354-9, két komponensével együtt:
app.post('/readings', express.json(), async (req, res, next) => {
try {
const user = currentUser(req);
const { systolic, diastolic, measuredAt } = req.body;
if (![systolic, diastolic].every((v) => Number.isFinite(v) && v > 20 && v < 300)) {
throw new HttpError(400, 'systolic and diastolic must be numbers in mmHg');
}
const obs = await anpheros.observations.create(user.patientId, {
code: '85354-9',
category: 'vital-signs',
effective_at: measuredAt ?? new Date().toISOString(),
components: [
{ code: '8480-6', value: systolic, unit: 'mm[Hg]' },
{ code: '8462-4', value: diastolic, unit: 'mm[Hg]' },
],
author_type: 'patient',
}, { source_system: 'bp-app' });
res.status(201).json({ id: obs.id, measuredAt: obs.effective_at });
} catch (e) { next(e); }
});
Amit az Anpheros tárol és visszaad:
{"id": "78188270-e65e-49bd-89d0-e776226e9614", "patient": "27296656-…", "code": "85354-9", "system": "http://loinc.org",
"display": "Blood pressure panel", "category": "vital-signs", "effective_at": "2026-10-10T08:30:00Z",
"components": [{"code": "8480-6", "system": "http://loinc.org", "value": 138.0, "unit": "mm[Hg]"},
{"code": "8462-4", "system": "http://loinc.org", "value": 88.0, "unit": "mm[Hg]"}],
"status": "final", "updated_at": "2026-10-12T20:16:51.153Z", "fhir": "Observation/78188270-…"}
Az SDK minden létrehozáskor küld egy Idempotency-Key, így egy hálózati hiba utáni újrapróbálkozás nem tárolja kétszer a mérést. A author_type: 'patient' és a source_system a mérés származási adataiba kerülnek: egy orvos, egy másik alkalmazás vagy egy AI modell később meg tudja állapítani, hogy a személy otthon mérte ezt az Ön alkalmazásával.
4. lépés: Olvasd vissza a leleteket
app.get('/readings', async (req, res, next) => {
try {
const user = currentUser(req);
const page = await anpheros.observations.list(user.patientId, {
code: '85354-9',
from: typeof req.query.from === 'string' ? req.query.from : undefined,
limit: 50,
});
res.json({
readings: page.data.map((o) => ({
id: o.id,
measuredAt: o.effective_at,
systolic: o.components.find((c) => c.code === '8480-6')?.value,
diastolic: o.components.find((c) => c.code === '8462-4')?.value,
})),
next: page.next_cursor,
});
} catch (e) { next(e); }
});
Az API-d a kívánt alakban adja vissza az adatokat az alkalmazásodnak. A tárolt adatok szabványosak maradnak. Mivel a felhasználói azonosítót a currentUser ellenőrzi, egy felhasználó soha nem kérdezhet le más felhasználó betegazonosítóját.
5. lépés: hibák
Az Anpheros hibák AnpherosError formátumban érkeznek, status, type, message, field és egy requestId mezővel. A validációs hibákat továbbítsa az alkalmazásnak, a többit pedig rejtse el:
app.use((err: unknown, _req: express.Request, res: express.Response, _next: express.NextFunction) => {
if (err instanceof HttpError) return res.status(err.status).json({ error: err.message });
if (err instanceof AnpherosError && err.status === 400) {
return res.status(400).json({ error: err.message, field: err.field });
}
console.error(err instanceof AnpherosError ? `anpheros ${err.status} ${err.type} request=${err.requestId}` : err);
res.status(502).json({ error: 'medical record service unavailable, try again' });
});
Például egy dátum nélküli leolvasást az Anpheros {"error": {"type": "invalid", "message": "Field required (at effective_at)", "field": "effective_at"}} hibával utasít el. A sebességhatárokat (429) és a szerverhibákat az SDK megpróbálja újra, mielőtt azok megjelennek. Naplózza a requestId értéket, és hivatkozzon rá, ha kapcsolatba lép a támogatással. A teljes lista az Hibák oldalon található.
6. lépés: Értesülj az új adatokról webhookon keresztül
Az olvasmányok máshonnan is érkezhetnek: egy klinika, amely ugyanabba a rekordba ír, egy laborjelentés, egy másik alkalmazás, amelyhez a személy csatlakozott. Regisztrálj egy végpontot egyszer:
curl -X POST https://platform.anpheros.com/v1/webhooks -H "Authorization: Bearer $ANPHEROS_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://bp.example/webhooks/anpheros", "events": ["resource.created", "consent.revoked"]}'
A válasz tartalmaz egy secret (whsec_…) értéket, amely csak egyszer jelenik meg. Minden kézbesítést ellenőrizz a nyers törzs alapján, mielőtt megbízol benne:
app.post('/webhooks/anpheros', express.raw({ type: 'application/json' }), async (req, res) => {
const ok = await verifyWebhookSignature({
secret: process.env.ANPHEROS_WEBHOOK_SECRET!,
header: req.header('anpheros-signature'),
body: req.body as Buffer,
});
if (!ok) return res.status(400).end();
const event = JSON.parse((req.body as Buffer).toString('utf8'));
// Events carry ids and versions, not clinical data: fetch what you need, then update caches or notify.
console.log(event.type, event.data);
res.status(204).end();
});
app.listen(3000, () => console.log('bp-api on http://localhost:3000'));
Az eseménytípusok: resource.created, resource.updated, resource.deleted, consent.granted, consent.revoked, document.finalized és ping. A kézbesítések alá vannak írva, újrapróbálkozhatók, és lejátszhatók (Webhooks).
Futtatás
npx tsx server.ts
curl -X POST localhost:3000/signup -H 'content-type: application/json' \
-d '{"email":"[email protected]","given":"Ioana","family":"Marin","birthDate":"1979-04-12"}'
# {"userId":"…"}
curl -X POST localhost:3000/readings -H 'content-type: application/json' -H 'x-user-id: <userId>' \
-d '{"systolic":138,"diastolic":88,"measuredAt":"2026-10-10T08:30:00Z"}'
curl localhost:3000/readings -H 'x-user-id: <userId>'
Cserélje le a x-user-id helyőrzőt a valós hitelesítő adataival, mielőtt bármi is elhagyná a gépet.
További lépések
- Már létező rekorddal rendelkező személyek. Egy API kulcs eléri a projektje által létrehozott betegeket. Egy személy meglévő rekordjához való csatlakozáshoz, amelyet más alkalmazások, klinikák vagy laboratóriumok gyűjtöttek, használja az OAuth-ot és a beleegyezésüket: Beteg beleegyezés implementálása SMART on FHIR segítségével.
- Szigorú FHIR, ha szükséges. A
anpheros.fhir.search,create,transaction,everythingéssummaryugyanazokkal az azonosítókkal biztosítja a FHIR R4 API elérését. - AI funkciók. A
anpheros.context.buildegy forrás-címkézett kontextust készít elő egy modell számára: AI alapú egészségügyi alkalmazás építése FHIR backenddel. - Éles környezet. Az éles környezet kulcsait (
sk_live_…) igazolt szervezetek kapják meg aláírt DPA-val; lásd: Árazás és Korlátok és sebességkorlátok.
Gyakran ismételt kérdések
Szükségem van saját adatbázisra az orvosi adatokhoz?
Nem maguk az orvosi adatokhoz. Az Ön adatbázisa tárolja a felhasználókat, a munkameneteket és a termékbeállításokat, valamint minden felhasználóhoz tartozó betegazonosítót. Az észlelések, állapotok, gyógyszerek, dokumentumok, azok története és a szerzőik a FHIR rekordban tárolódnak.
Hívhatja-e a mobilalkalmazás közvetlenül az Anpheros-t?
API kulccsal nem: a kulcs eléri a projekt minden betegét, és a szerverén kell maradnia. Egy mobilalkalmazás közvetlenül hívhatja az Anpheros-t egy OAuth token segítségével, amelyet az illető a saját rekordjára engedélyezett, mint például a Hogyan készítsünk egészségügyi alkalmazást Flutterrel című cikkben.
Melyik keretrendszerrel működik ez?
Bármelyikkel. Az SDK csak fetch-ra van szüksége, így fut Express, Fastify, Hono, NestJS, Next.js route handlers, Deno vagy Bun környezetben.
Kapcsolódó
- Egészségügyi API: mire figyeljen egy egészségügyi API esetén, és az Anpheros API áttekintése
- Orvosi adat API: hova kerül az egyes orvosi adatok típusai
- Orvosi rekordok tárolása FHIR R4 használatával
- Webhookok és Hibák
- Orvosi alkalmazás backend és adatbázis
Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card