Skip to content

monfortbrian/openmrs-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

openmrs-sdk

npm version npm downloads bundle size zero dependencies TypeScript License: MIT

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-sdk
yarn add openmrs-sdk
pnpm add openmrs-sdk

Quick 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

search returns the raw FHIR Bundle. list returns 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:  Admin123

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Related Projects

License

MIT - Copyright (c) 2026 Monfort Brian N.

Support


Made with ❤️ for the global health community

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors