Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card
TypeScript ile Sağlık API'si Nasıl Oluşturulur
Öğretici: hasta kayıtları oluşturan, kan basıncı okumalarını FHIR R4 gözlemleri olarak saklayan, bunları geri okuyan, hataları eşleyen ve webhook'ları doğrulayan bir TypeScript Express API'si — kendi tıbbi veritabanınız olmadan.
Bu eğitim, Express ile TypeScript'te bir kan basıncı takip uygulamasının arka uç API'sini oluşturur: kayıt olma, kullanıcının tıbbi kaydını oluşturur, okumalar kodlanmış HL7 FHIR R4 gözlemleri olarak saklanır, uygulama bunları geri okur ve bir webhook uç noktası kendi tıbbi veritabanınız olmadan yeni veriler hakkında bilgi verir. API'niz ürününüze özgü olanları (kullanıcılar, oturumlar, ayarlar) saklar. Tıbbi veriler, geçmişi, onayı ve kaynağı, TypeScript SDK aracılığıyla çağırdığınız Anpheros'ta bulunur.
Mimari
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 ──────────────┘
Veritabanınız her kullanıcı için fazladan bir sütun depolar: Anpheros hasta kimlikleri. Klinik her şey API'den geçer, bu nedenle kodlanmış, sürümlenmiş ve herhangi bir FHIR sistemi veya hastanın izin verdiği diğer uygulamalar tarafından okunabilir durumdadır. Tıbbi uygulama arka ucu ve veritabanı bölümü bu ayrımı ayrıntılı olarak açıklar.
Başlamadan Önce
- Node.js 18 veya daha yeni sürüm.
- platform.anpheros.com/dashboard adresinden bir sandbox anahtarı (
sk_test_…) (Bir sandbox anahtarı alın). Anahtarı yalnızca sunucuda saklayın; uygulamaya asla ulaşmamalıdır.
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_…
Adım 1: İstemci ve kullanıcı deponuz
// 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); }
}
Adım 2: Kayıt işlemi tıbbi kaydı oluşturur
Biri kaydolduğunda, Anpheros'ta hastasını oluşturun ve kendi kullanıcı kimliğinizi identifiers içine yerleştirin, böylece kayıt her zaman sizin tarafınızdan bulunabilir:
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); }
});
Anpheros'tan gelen yanıt, projenize ait bir id ve FHIR referansıyla birlikte yeni hastadır:
{"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"}
Adım 3: Bir okuma kaydetme
Uygulama {systolic, diastolic, measuredAt} gönderir. API'niz bunu doğrular ve iki bileşeniyle birlikte LOINC 85354-9 olan bir kan basıncı gözlemi depolar:
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); }
});
Anpheros'un depoladığı ve döndürdüğü:
{"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-…"}
SDK, her oluşturma işlemiyle birlikte bir Idempotency-Key gönderir, böylece ağ hatası sonrası yeniden deneme okumayı iki kez kaydetmez. author_type: 'patient' ve source_system okumanın kaynağına gider: bir doktor, başka bir uygulama veya bir yapay zeka modeli daha sonra kişinin bunu evde sizin uygulamanızla ölçtüğünü anlayabilir.
Adım 4: Okumaları Geri Oku
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); }
});
API'niz, uygulamanızın istediği şekli döndürür. Saklanan veriler standart kalır. Kullanıcı kimliği currentUser tarafından kontrol edildiği için, bir kullanıcı asla başka bir kullanıcının hasta kimliğini isteyemez.
Adım 5: Hatalar
Anpheros hataları AnpherosError ile birlikte status, type, message, field ve bir requestId olarak gelir. Doğrulama hatalarını uygulamaya iletin ve diğerlerini gizleyin:
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' });
});
Örneğin, tarihi olmayan bir okuma Anpheros tarafından {"error": {"type": "invalid", "message": "Field required (at effective_at)", "field": "effective_at"}} ile reddedilir. SDK, oran sınırları (429) ve sunucu hataları gibi durumları siz görmeden önce yeniden dener. requestId'ü günlüğe kaydedin ve destekle iletişime geçerseniz bunu belirtin. Tam liste Hatalar bölümünde yer almaktadır.
Adım 6: Webhook ile Yeni Verilerden Haberdar Olun
Okumalar başka yerlerden de gelebilir: aynı kayda yazan bir klinik, bir laboratuvar raporu, kişinin bağladığı başka bir uygulama. Bir kez bir uç nokta kaydedin:
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"]}'
Yanıt, bir kez gösterilen bir secret (whsec_…) içerir. Güvenmeden önce her teslimatı ham gövdeye karşı doğrulayın:
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'));
Olay türleri resource.created, resource.updated, resource.deleted, consent.granted, consent.revoked, document.finalized ve ping'dur. Teslimatlar imzalanır, yeniden denenir ve yeniden oynatılabilir (Webhook'lar).
Çalıştırın
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>'
Bir şey makinenizden ayrılmadan önce, x-user-id yer tutucusunu gerçek kimlik bilgilerinizle değiştirin.
İleriye Gitmek
- Zaten kaydı olan kişiler. Bir API anahtarı, projenizin oluşturduğu hastalara ulaşır. Başka uygulamalar, klinikler veya laboratuvarlar tarafından toplanan bir kişinin mevcut kaydına bağlanmak için OAuth ve onların onayını kullanın: SMART on FHIR ile hasta onayını uygulama.
- İhtiyacınız olduğunda Strict FHIR.
anpheros.fhir.search,create,transaction,everythingvesummary, aynı kimliklerle size FHIR R4 API sunar. - Yapay Zeka özellikleri.
anpheros.context.build, bir model için kaynak etiketli bir bağlam hazırlar: FHIR arka ucu ile bir Yapay Zeka sağlık uygulaması oluşturma. - Üretim. Üretim anahtarları (
sk_live_…), imzalanmış bir DPA'ya sahip doğrulanmış kuruluşlara verilir; Fiyatlandırma ve Sınırlar ve hız sınırları bölümlerine bakın.
Sıkça Sorulan Sorular
Tıbbi veriler için kendi veritabanıma ihtiyacım var mı?
Tıbbi verilerin kendisi için hayır. Veritabanınız kullanıcıları, oturumları ve ürün ayarlarını, ayrıca her kullanıcı için hasta kimliğini saklar. Gözlemler, durumlar, ilaçlar, belgeler, bunların geçmişi ve kimin yazdığı FHIR kaydında saklanır.
Mobil uygulama Anpheros'u doğrudan çağırabilir mi?
API anahtarıyla hayır: anahtar projenizin her hastasına ulaşır ve sunucunuzda kalmalıdır. Mobil uygulama, kişinin kendi kaydı için verdiği bir OAuth jetonu ile Anpheros'u doğrudan çağırabilir, Flutter ile sağlık uygulaması nasıl oluşturulur bölümünde olduğu gibi.
Hangi çerçeve ile çalışır?
Herhangi biri. SDK yalnızca fetch gerektirir, bu nedenle Express, Fastify, Hono, NestJS, Next.js rota işleyicileri, Deno veya Bun'da çalışır.
İlgili Konular
- Sağlık API'si: Bir sağlık API'sinde nelere dikkat etmeli ve Anpheros API'sine genel bir bakış
- Tıbbi Veri API'si: Her tür tıbbi verinin nereye gittiği
- FHIR R4 Kullanarak Tıbbi Kayıtların Nasıl Saklanacağı
- Webhook'lar ve Hatalar
- Tıbbi Uygulama Arka Ucu ve Veritabanı
Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card