SDKs
The Dart / Flutter (anpheros_sdk) and TypeScript (@anpheros/sdk) clients: same shape, idempotent creates, retries, token refresh and the consent flow.
Anpheros is interoperable medical-data infrastructure for building healthcare applications, medical software and AI services. Each patient has one HL7 FHIR R4 record that they control; applications, clinics, laboratories and AI agents read and write it through the Anpheros Platform API — with patient consent (OAuth 2.1 / SMART on FHIR), provenance on every write and an access log the patient can see. This repository contains the official client libraries and runnable examples.
| Language | Package | Install | Source |
|---|---|---|---|
| Dart / Flutter | anpheros_sdk |
dart pub add anpheros_sdk |
dart/anpheros_sdk |
| TypeScript (Node 18+, browsers, Deno, Bun) | @anpheros/sdk |
npm install @anpheros/sdk |
ts |
Who it is for
Developers building patient and family health apps, medical-app backends, clinic and laboratory integrations, and AI assistants or agents that need a patient's structured medical context — without designing a medical database, a consent system and an audit trail from scratch.
Get a sandbox key
The sandbox is free and self-service. Sign in with Google on the dashboard and press Get a sandbox key: you get a sandbox project and a key instantly. Every sandbox project comes with its own 30 synthetic patients — six months of conditions, medications, allergies, lab results and vital signs — that you can change freely and reset at any time. Sandbox keys (sk_test_…) never reach real patient data.
When you go live, production is for verified organisations with a data processing agreement, and production starts at €49 a month with the first month free (pricing).
Connect
import { Anpheros, apiKey } from '@anpheros/sdk';
const anpheros = new Anpheros({ auth: apiKey(process.env.ANPHEROS_KEY!) }); // sk_test_… in the sandbox
const { data: patients } = await anpheros.patients.list();
const labs = await anpheros.observations.list(patients[0].id, { category: 'laboratory', limit: 10 });
const ctx = await anpheros.context.build({ patient: patients[0].id, task: 'weekly check-in', budget_tokens: 1500, format: 'text' });
import 'package:anpheros_sdk/anpheros_sdk.dart';
final anpheros = Anpheros(auth: AnpherosAuth.apiKey('sk_test_…'));
final patients = await anpheros.patients.list();
final labs = await anpheros.observations.list(patients.data.first.id, category: 'laboratory', limit: 10);
API keys belong on servers. An app acting for a person uses OAuth instead: both SDKs implement the consent flow (authorization code + PKCE) and refresh tokens automatically.
What the SDKs cover
Both cover the whole public surface (/v1, /fhir/R4, /oauth/token, /oauth/revoke) with the
same shape: patients, observations, conditions, medications, documents, timeline,
provenance, context, grants, terminology and raw fhir. A test fails the
build when a public route is missing from either SDK or when an SDK calls a route the server
does not have.
Both SDKs: automatic Idempotency-Key on creates, retries with backoff on 429/5xx, one token
refresh on 401, typed errors with the request id, PKCE helpers and the consent flow.
Medical data and FHIR
The record is made of standard FHIR R4 resources — 26 types, including Observation, Condition, MedicationStatement, DocumentReference, Immunization and AllergyIntolerance — coded with LOINC, ICD-10, ATC and UCUM. The REST API (/v1) and the FHIR API (/fhir/R4) read and write the same resources with the same ids; fhir in both SDKs gives raw FHIR access (search, transactions, $everything, $summary, $validate).
Examples
| Example | Shows |
|---|---|
| quickstart-ts | write and read a record: measurements, lab result, diagnosis, medication, timeline, FHIR search, IPS, AI context |
| quickstart-dart | the same from Dart / Flutter |
| consent-app-ts | a web app that asks for consent (OAuth 2.1 + PKCE) and reads the person's record |
| ai-context-llm | a question about a record answered by a model of your choice (local or hosted) |
| fhir-transaction | a FHIR R4 transaction bundle and the resulting International Patient Summary |
The examples run against the free sandbox, where each sandbox project has its own 30 synthetic patients — see Get a sandbox key.
Conformance
Raw test results, published so they can be checked (test results, not certifications): conformance/. On 28 September 2026 the Standalone Launch group of the Inferno SMART App Launch STU2 test kit (v1.0.3) passed 22 of 22 tests against the platform. EHR launch is not supported.
Documentation
- Developer guides: https://developers.anpheros.com/guides/
- SDK guide: https://developers.anpheros.com/guides/sdks
- API reference (OpenAPI): https://developers.anpheros.com/docs
- For AI assistants: https://developers.anpheros.com/llms.txt
- Anpheros: https://anpheros.com/
Issues and security
Report bugs in this repository's issues. Never include API keys, tokens or patient data in an issue. Security reports: [email protected].
License
Apache License 2.0 — see the LICENSE file of each package. Copyright 2026 Anpheros.
@anpheros/sdk
TypeScript client for Anpheros Platform: a FHIR R4 health record per patient, project
isolation, patient consent (OAuth 2.1 / SMART on FHIR), provenance on every write and an AI
context API. Runs anywhere fetch exists (Node 18+, browsers, Deno, Bun).
import { Anpheros, apiKey } from '@anpheros/sdk';
const anpheros = new Anpheros({ auth: apiKey(process.env.ANPHEROS_KEY!) });
const { data: patients } = await anpheros.patients.list();
const labs = await anpheros.observations.list(patients[0].id, { category: 'laboratory', limit: 10 });
const ctx = await anpheros.context.build({ patient: patients[0].id, task: 'weekly check-in', budget_tokens: 1500, format: 'text' });
Acting for a person:
import { OAuthFlow, OAuthAuth, generatePkce } from '@anpheros/sdk';
const flow = new OAuthFlow({ baseUrl: BASE, clientId: 'client_…', redirectUri: 'https://myapp.example/callback' });
const pkce = await generatePkce();
location.href = flow.authorizeUrl({ scopes: ['patient/Observation.rs?category=laboratory', 'offline_access'], state, pkce, lang: 'ro' });
// on the callback:
const tokens = await flow.exchange(code, pkce);
const anpheros = new Anpheros({ auth: new OAuthAuth({ tokens, onRefresh: flow.refresh, onTokens: persist }) });
Errors are AnpherosError (status, type, message, field, requestId). Creates send an
Idempotency-Key; 429/5xx are retried; expired tokens are refreshed once and the call retried.
anpheros_sdk
Dart / Flutter client for Anpheros Platform: a health-data backend with a FHIR R4 record per patient, project isolation, patient consent (OAuth 2.1 / SMART on FHIR), provenance on every write and an AI context API.
import 'package:anpheros_sdk/anpheros_sdk.dart';
final anpheros = Anpheros(auth: AnpherosAuth.apiKey('sk_test_…')); // server / sandbox
final patients = await anpheros.patients.list();
final elena = patients.data.first;
final labs = await anpheros.observations.list(elena.id, category: 'laboratory', limit: 10);
final ctx = await anpheros.context.build(ContextRequest(patient: elena.id, task: 'weekly check-in', budgetTokens: 1500));
Acting for a person (apps)
final flow = OAuthFlow(baseUrl: 'https://…', clientId: 'client_…', redirectUri: 'myapp://callback');
final pkce = Pkce.generate();
final url = flow.authorizeUrl(scopes: ['patient/Observation.rs?category=laboratory', 'patient/MedicationStatement.r', 'offline_access'],
state: 'abc', pkce: pkce, lang: 'ro');
// open `url`; on return with ?code=…:
final tokens = await flow.exchange(code: code, pkce: pkce);
final anpheros = Anpheros(auth: AnpherosAuth.oauth(
accessToken: tokens.accessToken, refreshToken: tokens.refreshToken, expiresAt: tokens.expiresAt,
onRefresh: flow.refresh, onTokens: persist));
final meds = await anpheros.medications.listMedications(tokens.patient!);
Every object carries fhir (its /fhir/R4 reference); anpheros.fhir gives raw FHIR access
(read, search, create, transaction, $everything, $summary, $validate).
Errors are AnpherosException with status, type, message, field and requestId.
Creates send an Idempotency-Key automatically; 429/5xx are retried with backoff; expired OAuth
tokens are refreshed once and the call retried.