AnpherosAnpheros PlatformDevelopers

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

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

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ó

Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card

Product updates by email

New features, guides and the end of the beta. One email a month at most.

Send me occasional Anpheros Platform updates by email (new features, API changes, guides). I'll confirm by email and can unsubscribe in one click from any email. Privacy