Retrieving and posting data

Retrieving and Posting Data

Frontend modules interact with the OpenMRS server via the APIs exposed by its modules. In general, most of the endpoints we use are provided by the FHIR Module (opens in a new tab). Most of the rest are provided by the REST Module (opens in a new tab), which is documented here (opens in a new tab).

Endpoints from the FHIR Module should always be preferred, when they are available. FHIR is an interoperability standard which OpenMRS supports.

Some data is available using higher-level functions or custom React Hooks provided by @openmrs/esm-framework. These should be used when available.

All of this functionality (React hooks excepted) is provided by the @openmrs/esm-api (opens in a new tab) package, which is part of @openmrs/esm-framework. The React hooks are in @openmrs/esm-react-utils (opens in a new tab), which is also part of @openmrs/esm-framework. See the API Docs (opens in a new tab).


To use the FHIR API, we recommend using SWR (opens in a new tab) based hooks and the openmrsFetch (opens in a new tab) fetcher function to retrieve data from the server. SWR offers a host of features that help us deliver an improved user experience.

Here's an example of using SWR to retrieve a patient from the FHIR API.

import useSWR from "swr";
import { fhirBaseUrl, openmrsFetch, fhir } from "@openmrs/esm-framework";
const { data, error, isLoading, mutate } = useSWR<fhir.Patient, Error>(

If you have questions about FHIR support in OpenMRS, you can ask in the FHIR Squad Slack channel (opens in a new tab).

Other OpenMRS server APIs

Some administrative endpoints will likely never have a proper representation in FHIR (e.g., endpoints for managing encounter types). When no suitable FHIR endpoint is available, you will want to use a different OpenMRS server API. The REST Web Services API (opens in a new tab) is used widely across many of our frontend modules.

Here's an example of a custom SWR hook that retrieves visits data.

import useSWR from "swr";
import { openmrsFetch, Visit } from "@openmrs/esm-framework";
interface VisitData {
  results: Array<Visit>;
/* Custom data fetching hook */
export function useVisits() {
  const url = `/ws/rest/v1/visit?includeInactive=false`;
  const { data, error, isLoading, mutate } = useSWR<{ data: VisitData }, Error>(
  return {
    visits: data,

We can leverage this useVisits hook in our visits component as follows:

const Visits = () => {
  const { visits, isError, isLoading } = useVisits();
  if (isLoading) {
    return <DataTableSkeleton role="progressbar" />
  if (error) {
    // render error state
  if (visits?.length) {
    // render visits
  return (
    // render empty state
export default Visits;

The mutate function returned by useSWR can be used to update the cache and trigger a re-render of the component. This is useful when we want to update the UI after a successful mutation.

const res = await saveVisitNote(payload);
try {
  if (res.status === 201) {
    // show success toast
} catch (error) {
  // handle error

Posting data to the server

Here's an example that demonstrates posting session data to the server.

import { openmrsFetch } from "@openmrs/esm-framework";
const abortController = new AbortController();
openmrsFetch("/ws/rest/v1/session", {
  method: "POST",
  body: {
    username: "hi",
    password: "there",
  signal: abortController.signal,

It is best practice for POST requests to have an AbortController (opens in a new tab). You should ensure that AbortController.abort() is called when the component is unmounted if the request is not yet completed.

In a React Component this is usually accomplished by making the request in a useEffect hook (opens in a new tab):

useEffect(() => {
  const abortController = new AbortController();
  return () => abortController.abort();
}, []);

API Objects

Some API objects are made available via React hooks (or via framework-agnostic subscriptions). The hooks are in @openmrs/esm-react-utils, and the subscription-yielding equivalents are in @openmrs/esm-api (opens in a new tab). See for example useVisitTypes (opens in a new tab) and the corresponding getVisitTypes (opens in a new tab).