openmrs-sdk
v1.0.0
Published
Lightweight, zero-dependency JavaScript/TypeScript client for the OpenMRS REST and FHIR R4 APIs. Works in Node.js, Deno, Bun, and modern browsers.
Maintainers
Readme
openmrs-sdk
Lightweight, zero-dependency JavaScript/TypeScript client for the OpenMRS REST and FHIR R4 APIs.
Works in Node.js 18+, Deno, Bun, and modern browsers - anywhere fetch is available.
Why openmrs-sdk?
The OpenMRS ecosystem has many frontend-specific packages (@openmrs/esm-*), but no standalone SDK for backend or server-side use. If you're building a Node.js integration, a CLI tool, a data pipeline, or any server-side application that talks to OpenMRS, you've been writing raw fetch calls with Basic Auth headers every time.
openmrs-sdk fills that gap:
Zero dependencies: just your runtime's built-in fetch
Dual API support: both REST and FHIR R4 from one client
Full TypeScript types: every response is fully typed
Tiny footprint: under 20KB minified + gzipped
Human-readable errors: "Authentication failed" not "401"
Installation
npm install openmrs-sdkyarn add openmrs-sdkpnpm add openmrs-sdkQuick Start
import { OpenMRS } from 'openmrs-sdk';
const client = new OpenMRS({
baseUrl: 'https://demo.openmrs.org/openmrs',
username: 'admin',
password: 'Admin123',
});
// Validate connection
const isConnected = await client.validate();
console.log('Connected:', isConnected);
// Search patients
const results = await client.patient.search({ q: 'John' });
console.log('Found:', results.results.length, 'patients');
// Get a specific patient
const patient = await client.patient.get('patient-uuid-here');
console.log('Patient:', patient.display);REST API
The REST API provides full access to OpenMRS resources with CRUD operations.
Patient
// Search by name or identifier
const results = await client.patient.search({ q: 'John Doe' });
// Get by UUID
const patient = await client.patient.get('abc-123-def-456');
// Create
const newPatient = await client.patient.create({
person: {
names: [{ givenName: 'Jane', familyName: 'Doe' }],
gender: 'F',
birthdate: '1990-01-15',
},
identifiers: [
{
identifier: 'MRN-001',
identifierType: 'identifier-type-uuid',
location: 'location-uuid',
},
],
});
// Update
await client.patient.update('abc-123', { person: { gender: 'M' } });
// Delete (void)
await client.patient.delete('abc-123', 'Duplicate record');Encounter
// Get all encounters for a patient
const encounters = await client.encounter.getByPatient('patient-uuid');
// Get specific encounter
const encounter = await client.encounter.get('encounter-uuid');
// Create encounter
const newEncounter = await client.encounter.create({
patient: 'patient-uuid',
encounterType: 'encounter-type-uuid',
encounterDatetime: '2026-01-15T10:30:00.000+0000',
obs: [
{
concept: 'concept-uuid',
value: 120,
},
],
});Observation
// Get all observations for a patient
const obs = await client.obs.getByPatient('patient-uuid');
// Get specific observation
const observation = await client.obs.get('obs-uuid');
// Create observation
await client.obs.create({
person: 'patient-uuid',
concept: 'concept-uuid',
obsDatetime: '2026-01-15T10:30:00.000+0000',
value: 37.5,
});Visit
// Get all visits for a patient
const visits = await client.visit.getByPatient('patient-uuid');
// Get specific visit
const visit = await client.visit.get('visit-uuid');
// Create visit
const newVisit = await client.visit.create({
patient: 'patient-uuid',
visitType: 'visit-type-uuid',
startDatetime: '2026-01-15T08:00:00.000+0000',
});
// End a visit
await client.visit.update('visit-uuid', {
stopDatetime: '2026-01-15T17:00:00.000+0000',
});Person
// Get person details
const person = await client.person.get('person-uuid');
// Search
const people = await client.person.search({ q: 'Jane' });
// Update demographics
await client.person.update('person-uuid', { gender: 'F' });Location
// List all locations
const locations = await client.location.list();
// Search
const results = await client.location.search({ q: 'Clinic' });
// Get specific location
const location = await client.location.get('location-uuid');Session
// Get current session info
const session = await client.session.get();
console.log('User:', session.user?.username);
console.log('Locale:', session.locale);
// Validate credentials
const valid = await client.session.validate();FHIR R4 API
The FHIR API provides standardized access to clinical data following the HL7 FHIR R4 specification.
FHIR Patient
// Get by ID
const patient = await client.fhir.patient.get('patient-uuid');
console.log(
'Name:',
patient.name?.[0]?.given?.join(' '),
patient.name?.[0]?.family,
);
// Search
const bundle = await client.fhir.patient.search({ name: 'John' });
// List (returns unwrapped array)
const patients = await client.fhir.patient.list({ _count: 20 });FHIR Observation
// Get all observations for a patient
const observations = await client.fhir.observation.list({
patient: 'patient-uuid',
_count: 100,
});
// Search with specific code
const vitals = await client.fhir.observation.search({
patient: 'patient-uuid',
code: '5085AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
});FHIR Condition
// Get diagnoses for a patient
const conditions = await client.fhir.condition.list({
patient: 'patient-uuid',
});FHIR Encounter
const encounters = await client.fhir.encounter.list({
patient: 'patient-uuid',
_count: 50,
});FHIR MedicationStatement
const medications = await client.fhir.medicationStatement.list({
patient: 'patient-uuid',
});FHIR DiagnosticReport
const reports = await client.fhir.diagnosticReport.list({
patient: 'patient-uuid',
});Configuration
const client = new OpenMRS({
// Required
baseUrl: 'https://demo.openmrs.org/openmrs',
username: 'admin',
password: 'Admin123',
// Optional
timeout: 30000, // Request timeout in ms (default: 30000)
});| Option | Type | Required | Default | Description |
| ---------- | -------- | -------- | ------- | ---------------------------------------------- |
| baseUrl | string | Yes | - | OpenMRS instance URL (include /openmrs path) |
| username | string | Yes | - | OpenMRS username |
| password | string | Yes | - | OpenMRS password |
| timeout | number | No | 30000 | Request timeout in milliseconds |
Error Handling
All errors throw OpenMRSError with clear, actionable messages:
import { OpenMRS, OpenMRSError } from 'openmrs-sdk';
try {
const patient = await client.patient.get('nonexistent-uuid');
} catch (error) {
if (error instanceof OpenMRSError) {
console.log(error.message); // "Resource not found: check the ID or endpoint"
console.log(error.status); // 404
console.log(error.statusText); // "Not Found"
console.log(error.body); // Raw response body
}
}| Status | Message | | ------ | -------------------------------------------------------------------- | | 401 | Authentication failed: check your username and password | | 403 | Access denied: your user does not have permission for this operation | | 404 | Resource not found: check the ID or endpoint | | 500 | OpenMRS server error: the server encountered an internal error | | 0 | Network error or request timeout |
Real-World Examples
Clinical Decision Support Pipeline
Pull patient data for AI-powered clinical insights:
const client = new OpenMRS({
baseUrl: 'https://my-clinic.org/openmrs',
username: 'integration-user',
password: 'secure-password',
});
// Gather comprehensive patient data
const patient = await client.fhir.patient.get(patientId);
const observations = await client.fhir.observation.list({
patient: patientId,
_count: 200,
});
const conditions = await client.fhir.condition.list({ patient: patientId });
const medications = await client.fhir.medicationStatement.list({
patient: patientId,
});
// Feed into your analysis pipeline
const clinicalSummary = {
demographics: patient,
labs: observations,
diagnoses: conditions,
treatments: medications,
};OpenMRS → DHIS2 Reporting
Aggregate clinical data for national health reporting:
// Fetch encounters for a reporting period
const encounters = await client.encounter.getByPatient(patientId);
// Count encounters by type for aggregate reporting
const malariaCases = encounters.results.filter(
(e) => e.encounterType.display === 'Malaria Consultation',
);
// Push count to DHIS2 via dhis2 API or n8n-nodes-dhis2
console.log(`Malaria cases this month: ${malariaCases.length}`);Bulk Patient Search
// Paginate through all patients
let startIndex = 0;
const allPatients = [];
while (true) {
const page = await client.patient.search({
v: 'default',
limit: 100,
startIndex,
});
allPatients.push(...page.results);
if (page.results.length < 100) break;
startIndex += 100;
}
console.log(`Total patients: ${allPatients.length}`);Express.js API Endpoint
import express from 'express';
import { OpenMRS } from 'openmrs-sdk';
const app = express();
const client = new OpenMRS({
baseUrl: process.env.OPENMRS_URL!,
username: process.env.OPENMRS_USER!,
password: process.env.OPENMRS_PASS!,
});
app.get('/api/patients/:id', async (req, res) => {
try {
const patient = await client.patient.get(req.params.id);
res.json(patient);
} catch (error) {
res.status(error.status || 500).json({ error: error.message });
}
});API Reference
REST Resources
| Resource | Methods |
| ----------- | ------------------------------------------------------------- |
| patient | get, search, create, update, delete |
| encounter | get, search, getByPatient, create, update, delete |
| obs | get, search, getByPatient, create, delete |
| visit | get, search, getByPatient, create, update, delete |
| person | get, search, update |
| location | get, search, list |
| session | get, validate |
FHIR R4 Resources
| Resource | Methods |
| -------------------------- | ----------------------- |
| fhir.patient | get, search, list |
| fhir.encounter | get, search, list |
| fhir.observation | get, search, list |
| fhir.condition | get, search, list |
| fhir.medicationStatement | get, search, list |
| fhir.diagnosticReport | get, search, list |
searchreturns the raw FHIRBundle.listreturns an unwrapped array of resources.
Compatibility
- Runtime: Node.js 18+, Deno, Bun, modern browsers
- OpenMRS: 2.3+ with FHIR2 module (for FHIR endpoints)
- Module: ESM and CommonJS (dual package)
- TypeScript: Full type definitions included
Demo Server
You can test against the OpenMRS demo server:
Base URL: https://demo.openmrs.org/openmrs
Username: admin
Password: Admin123Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Related Projects
- n8n-nodes-openmrs - n8n community node for OpenMRS workflow automation
- n8n-nodes-dhis2 - n8n community node for DHIS2 health data reporting
License
MIT - Copyright (c) 2026 Monfort Brian N.
Support
- Issues: GitHub Issues
- OpenMRS Wiki: wiki.openmrs.org
- FHIR R4 Spec: hl7.org/fhir/R4
Made with ❤️ for the global health community
