API examples for common MIRA workflows.
Copyable TypeScript examples for the flows developers usually ask about first: finding patients, writing patient resources, opening encounters, and adding billable charge items.
setup
Connect to Aidbox with a small transport.
The SDK does not ship a default HTTP client. This adapter is the reusable setup used by the examples below.
import {
FhirDeHttpError,
createFhirDeClient,
} from '@polaris/sdk/fhir'
import type { FhirResource, FhirTransport } from '@polaris/sdk/fhir'
const baseUrl = 'https://aidbox.example.com/fhir'
const transport: FhirTransport = {
async request(method, path, init) {
const normalizedPath = path.startsWith('/') ? path : `/${path}`
const url = new URL(`${baseUrl.replace(/\/$/, '')}${normalizedPath}`)
if (init?.query) {
for (const [key, value] of Object.entries(init.query)) {
const values = Array.isArray(value) ? value : [value]
for (const item of values) url.searchParams.append(key, item)
}
}
const res = await fetch(url, {
method,
headers: {
'Content-Type': 'application/fhir+json',
Accept: 'application/fhir+json',
Authorization: `Bearer ${process.env.AIDBOX_TOKEN}`,
...init?.headers,
},
body: init?.body == null ? undefined : JSON.stringify(init.body),
})
const body = res.status === 204 ? null : await res.json().catch(() => null)
if (!res.ok) throw new FhirDeHttpError(res.status, body)
return body
},
}
const client = createFhirDeClient({ baseUrl, transport })
async function putResource<T extends FhirResource>(resource: T): Promise<T> {
if (!resource.id) throw new Error('PUT requires resource.id')
return await transport.request(
'PUT',
`/${resource.resourceType}/${resource.id}`,
{ body: resource }
) as T
} patient lookup
Find and read patients.
Use the typed client when you want profile-wrapped resources and strict profile validation on server responses.
import {
KBV_PR_FOR_PatientProfile,
SYSTEM_KVID_10,
} from '@polaris/fhir-de'
const patients = client.forProfile(KBV_PR_FOR_PatientProfile, 'Patient')
// Lookup by GKV KVID-10 identifier
const matches = await patients.search({
identifier: `${SYSTEM_KVID_10}|A123456789`,
_count: '10',
})
// Read by stable FHIR id
const patient = await patients.read('pat-001')
if (patient === null) {
// Patient was not found. read(id) treats 404 as a valid absence.
} patient write
Create or update a patient resource.
Builder output is a plain FHIR resource. It can be written directly to Aidbox, NDJSON, or another FHIR server.
import { buildPatient } from '@polaris/fhir-de'
const patient = buildPatient({
id: 'pat-001',
firstName: 'Anna',
lastName: 'Müller',
birthDate: '1985-04-12',
gender: 'female',
kvid10: 'A123456789',
address: {
line: ['Hauptstraße 1'],
city: 'München',
postalCode: '80331',
country: 'DE',
},
})
await putResource(patient) visit
Open or update an encounter.
This mirrors a typical practice workflow: patient arrives, gets called, and the encounter is linked back to patient and organization.
import { buildEncounter } from '@polaris/fhir-de'
const encounter = buildEncounter({
id: 'enc-2026-04-27-001',
status: 'in-progress',
class: {
system: 'http://terminology.hl7.org/CodeSystem/v3-ActCode',
code: 'AMB',
display: 'ambulatory',
},
subject: { reference: 'Patient/pat-001' },
serviceProvider: { reference: 'Organization/org-001' },
period: { start: '2026-04-27T09:00:00+02:00' },
arrivalTime: '2026-04-27T08:55:00+02:00',
calledTime: '2026-04-27T09:05:00+02:00',
})
await putResource(encounter) billing
Add EBM and GOÄ charge items.
ChargeItems link billable services to the patient and encounter. EBM uses the German ChargeItem EBM profile; GOÄ and other private billing systems are emitted as plain R4 ChargeItem resources.
import {
SYSTEM_EBM,
SYSTEM_GOAE,
buildChargeItem,
} from '@polaris/fhir-de'
const ebm03000 = buildChargeItem({
id: 'charge-ebm-03000-001',
status: 'billable',
code: {
system: SYSTEM_EBM,
code: '03000',
display: 'Versichertenpauschale',
},
subject: { reference: 'Patient/pat-001' },
context: { reference: 'Encounter/enc-2026-04-27-001' },
occurrenceDateTime: '2026-04-27T09:15:00+02:00',
performer: [{ actor: { reference: 'Practitioner/prac-001' } }],
quantity: { value: 1 },
})
const goae1 = buildChargeItem({
id: 'charge-goae-1-001',
status: 'billable',
code: {
system: SYSTEM_GOAE,
code: '1',
display: 'Beratung',
},
subject: { reference: 'Patient/pat-001' },
context: { reference: 'Encounter/enc-2026-04-27-001' },
occurrenceDateTime: '2026-04-27T09:20:00+02:00',
performer: [{ actor: { reference: 'Practitioner/prac-001' } }],
quantity: { value: 1 },
factorOverride: 2.3,
})
await putResource(ebm03000)
await putResource(goae1) billing lookup
Load charge items for an encounter.
For resource types without a profile-scoped client, call the same transport directly and keep the result as a FHIR Bundle.
const chargeItemBundle = await transport.request('GET', '/ChargeItem', {
query: {
context: 'Encounter/enc-2026-04-27-001',
_count: '50',
},
})
// chargeItemBundle is the raw FHIR Bundle returned by the server. llm gateway
Route LLM requests with capability checks.
Import PII-safe prompt types, capability routing, and PII scanning from @polaris/sdk/llm. Use @polaris/fhir-de directly for resource builders (buildPatient, buildEncounter, etc.) — @polaris/sdk/llm is for the LLM gateway client API.
import {
AnonymizedPrompt,
routeRequest,
scanForPii,
NoopAuditStore,
} from '@polaris/sdk/llm'
// Construct a PII-safe prompt (must have been anonymized before calling from())
const prompt = AnonymizedPrompt.from({ anonymizedText: 'Diagnose: Hypertonie' })
// Check text for PII before constructing an AnonymizedPrompt
const piiResult = scanForPii('Patient: Max Mustermann, geb. 01.01.1980')
if (piiResult.hasPii) {
// Anonymize or redact before proceeding
console.log('PII detected:', piiResult.matches)
}
// Route a request through the LLM gateway
const auditStore = new NoopAuditStore()
const result = await routeRequest(
{ intentId: 'summarize-encounter', prompt },
{ auditStore }
) anonymized mode
Anonymisierte Antworten mit piiMode.
Mit piiMode: 'anonymized' werden PII-Felder (Namen, Adressen, Kontaktdaten) aus allen FHIR-Antworten entfernt, bevor sie zurückgegeben werden. Nützlich für Entwicklungs- und Testumgebungen oder für KI-Agenten ohne direkten Patientendatenzugriff.
import {
createFhirDeClient,
AnonymizingTransport,
} from '@polaris/sdk/fhir'
import { KBV_PR_FOR_PatientProfile } from '@polaris/fhir-de'
// POLARIS_ANON_SALT must be set in the environment.
// createFhirDeClient throws synchronously if it is missing.
// process.env.POLARIS_ANON_SALT = 'my-secret-salt'
const anonClient = createFhirDeClient({
baseUrl,
transport,
piiMode: 'anonymized',
})
const patients = anonClient.forProfile(KBV_PR_FOR_PatientProfile, 'Patient')
// Patient names, addresses, identifiers, and contact info are removed.
// IDs are deterministically hashed: SHA-256(salt:id) → 'anon-<12hex>'.
const patient = await patients.read('pat-001')
// patient.id → 'anon-3f8a1c20b7d9' (hashed)
// patient.resource.name → undefined (PII removed)
// patient.resource.address → undefined (PII removed)
// References within resources are also rewritten consistently:
// 'Patient/pat-001' → 'Patient/anon-3f8a1c20b7d9'
// To use AnonymizingTransport directly (e.g. to pass an explicit salt in tests):
const anonTransport = new AnonymizingTransport(transport, 'test-salt')
const testClient = createFhirDeClient({ baseUrl, transport: anonTransport }) Resource builders stay in @polaris/fhir-de.
buildPatient, buildEncounter, and the other builders are exported from @polaris/fhir-de directly. @polaris/sdk/fhir exposes the typed client API — not the builders.
LLM types live in @polaris/sdk/llm.
All LLM gateway types — AnonymizedPrompt, routeRequest, scanForPii — are available from @polaris/sdk/llm. Hono and server-runtime symbols are excluded from this subpath.
Use Polaris Platform for operations.
The SDK builds and reads FHIR resources. Sync scheduling, PVS writeback, audit trails, and multi-tenant lifecycle are handled by the Polaris Platform and adapter APIs.