FHIR API Basics
The Oystehr FHIR API is a RESTful API conforming to the FHIR specification (opens in a new tab). It uses the JSON format (opens in a new tab) for resource representation.
Anatomy of a FHIR Resource
A FHIR resource is a JSON object with a resourceType
property and a set of additional properties that vary depending on the resource type. The Patient resource is at the heart of the FHIR universe, and many other FHIR resources reference Patient resources. Let's take a look at an example Patient resource:
{
"resourceType": "Patient",
"active": true,
"name": [
{
"given": ["Jon"],
"family": "Snow"
}
],
"address": [
{
"use": "home",
"type": "physical",
"text": "Winterfell"
}
]
}
- The
resourceType
ofPatient
is what makes this a Patient FHIR resource. - The
active
property is a boolean indicating whether this Patient record is in active use. - You can see from the
name
property that the patient the FHIR resource represents is named Jon Snow. Thename
property is an array of type HumanName (opens in a new tab), which allows for the possibility of recording a patient's official name, maiden name, nickname, etc. - The
address
property is also an array so you can document a number of addresses for a patient. This can be useful when a patient's address changes and you want to keep a record of their previous address.
Compare our Jon Snow Patient resource to the Patient resource definition (opens in a new tab) in the FHIR specification, and you'll see we are just scratching the surface of the information you can record in a Patient resource.
All of the properties are optional, so you can record as much or as little information as you need for your use case. It's common for a Patient resource to be created with limited information when a patient is first registered, and for that resource to grow over time as more information becomes available.
Create
Request
You can create a Patient resource by making a POST request to the Patient endpoint. The body of the request should be a JSON representation of the Patient resource. Patients can also be created using the SDK and the Developer Console.
Create a FHIR Patient with the v3 SDK:
import { Patient } from 'fhir/r4b'; // npm install @types/fhir
import Oystehr from '@oystehr/sdk'
const oystehr = new Oystehr({
accessToken: "<your_access_token>",
});
const createdResource/*: Patient*/ = await oystehr.fhir.create<Patient>({
resourceType: 'Patient',
active: true,
name: [
{
given: ['Jon'],
family: 'Snow',
},
],
address: [
{
use: 'home',
type: 'physical',
text: 'Winterfell',
},
],
});
Any time a FHIR Resource is created, updated, or deleted, Oystehr automatically creates a FHIR Provenance resource to track the change.
Response
The API responds with status code 201 Created
and a response body in JSON format containing the created Patient resource:
{
"resourceType": "Patient",
"active": true,
"name": [
{
"given": ["Jon"],
"family": "Snow"
}
],
"address": [
{
"use": "home",
"type": "physical",
"text": "Winterfell"
}
],
"id": "2419a78e-4c0a-411d-b9e2-90dc081f5efa",
"meta": {
"versionId": "6b43753b-08f1-4c71-afa8-c83704e42aab",
"lastUpdated": "2023-11-15T17:48:11.240Z"
}
}
There are a few new properties added to the FHIR Patient resource now that it has been created:
- The
id
property is a unique identifier for the Patient resource. This identifier is generated by the Oystehr FHIR API and is guaranteed to be unique across all Patient resources. - The
meta
property contains metadata about the Patient resource. ThelastUpdated
property is a timestamp indicating when the Patient resource was last updated. TheversionId
property is a unique identifier for the current version of the Patient resource. See Resource History for more information about FHIR resource versioning.
Read
Request
You can read a Patient resource by making a GET request to the Patient endpoint with the Patient resource's id
as a path parameter. Patients can also be read using the SDK and the Developer Console.
Read a FHIR Patient with the v3 SDK:
import { Patient } from 'fhir/r4b'; // npm install @types/fhir
import Oystehr from '@oystehr/sdk'
const oystehr = new Oystehr({
accessToken: "<your_access_token>",
});
const readResult/*: Patient*/ = await oystehr.fhir.get<Patient>({
resourceType: 'Patient',
resourceId: '2419a78e-4c0a-411d-b9e2-90dc081f5efa',
});
Response
The API responds with status code 200 OK
and a response body in JSON format containing the Patient resource.
{
"resourceType": "Patient",
"active": true,
"name": [
{
"given": ["Jon"],
"family": "Snow"
}
],
"address": [
{
"use": "home",
"type": "physical",
"text": "Winterfell"
}
],
"id": "2419a78e-4c0a-411d-b9e2-90dc081f5efa",
"meta": {
"versionId": "6b43753b-08f1-4c71-afa8-c83704e42aab",
"lastUpdated": "2023-11-15T17:48:11.240Z"
}
}
Update
You can update a FHIR resource with either PUT or PATCH requests. PUT requests replace the entire resource, while PATCH requests only update the properties you specify.
PUT
Update a Patient with PUT using the v3 SDK:
import { Patient } from 'fhir/r4b'; // npm install @types/fhir
import Oystehr from '@oystehr/sdk'
const oystehr = new Oystehr({
accessToken: "<your_access_token>",
});
const updateResult/*: Patient*/ = await oystehr.fhir.update<Patient>({
resourceType: 'Patient',
id: '2419a78e-4c0a-411d-b9e2-90dc081f5efa',
name: [{
given: [
'Aegon'
],
family: 'Targaryen'
}],
});
The meta
property is system-generated and read-only, so if you include it in your request, the API will just ignore it. The id
property is required in the resource content, and it must match the id
value passed in the URL path.
The API responds with status code 200 OK
and a response body containing the Patient resource, just like the Create and Read responses.
PATCH
JSON Patch
The FHIR specification requires one of a few implementations for PATCH behavior (opens in a new tab). The Oystehr FHIR API implements JSON Patch (opens in a new tab). The JSON Patch implementation requires a Content-Type
header of application/json-patch+json
and a request body containing an array of operations to perform on the resource.
Update a Patient with PATCH using the v3 SDK:
import { Patient } from 'fhir/r4b'; // npm install @types/fhir
import Oystehr from '@oystehr/sdk'
const oystehr = new Oystehr({
accessToken: "<your_access_token>",
});
const patchResult/*: Patient*/ = oystehr.fhir.patch<Patient>({
resourceType: 'Patient',
resourceId: '2419a78e-4c0a-411d-b9e2-90dc081f5efa',
operations: [
{
op: 'replace',
path: '/name',
value: [
{
given: [
"Aegon"
],
family: "Targaryen"
}
],
},
],
});
The API responds with status code 200 OK
and a response body containing the Patient resource, just like the Create and Read responses.
XML Patch
XML Patch is not supported by the Oystehr FHIR service. Please use JSON Patch instead.
FHIRPath Patch
FHIRPath Patch is not supported by the Oystehr FHIR service. Please use JSON Patch instead.
Handling Resource Contention with Optimistic Locking
To better handle concurrent write operations performed on resources, FHIR supports "weak" optimistic locking (opens in a new tab). When this behavior is enabled, the Oystehr FHIR service will not allow a resource to be updated if the client's version of the resource is out of date. To enable optimistic locking, the client must include the If-Match
header with the version ID of the resource it read before attempting to update the resource.
Optimistic locking is supported for both PUT and PATCH requests. The SDK makes it easier to use this feature by only requiring the resource version ID, instead of the whole If-Match
header.
Update a Patient with optimistic locking using the v3 SDK:
import { Patient } from 'fhir/r4b'; // npm install @types/fhir
import Oystehr from '@oystehr/sdk'
const oystehr = new Oystehr({
accessToken: "<your_access_token>",
});
const createdPatient = await oystehr.fhir.create<Patient>({
resourceType: 'Patient',
});
// a later update to the patient record
const updateResult/*: Patient*/ = await oystehr.fhir.update<Patient>({
resourceType: 'Patient',
id: createdPatient.id,
name: [{
given: [
'Aegon'
],
family: 'Targaryen'
}],
}, { optimisticLockingVersionId: createdPatient.meta?.versionId });
Patch a Patient with optimistic locking using the v3 SDK:
import { Patient } from 'fhir/r4b'; // npm install @types/fhir
import Oystehr from '@oystehr/sdk'
const oystehr = new Oystehr({
accessToken: "<your_access_token>",
});
const createdPatient = await oystehr.fhir.create<Patient>({
resourceType: 'Patient',
});
// a later patch to the patient record
const patchResult/*: Patient*/ = oystehr.fhir.patch<Patient>({
resourceType: 'Patient',
resourceId: createdPatient.id,
operations: [
{
op: 'replace',
path: '/name',
value: [
{
given: [
"Aegon"
],
family: "Targaryen"
}
],
},
],
}, { optimisticLockingVersionId: createdPatient.meta?.versionId });
Delete
Delete a resource by making a DELETE request to the Patient endpoint with the resource's id
as a path parameter.
Delete a Patient using the v3 SDK:
import { Patient } from 'fhir/r4b'; // npm install @types/fhir
import Oystehr from '@oystehr/sdk'
const oystehr = new Oystehr({
accessToken: "<your_access_token>",
});
await oystehr.fhir.delete<Patient>({
resourceType: 'Patient',
resourceId: '2419a78e-4c0a-411d-b9e2-90dc081f5efa',
});
The API responds with status code 204 No Content
and an empty response body.
Reference Properties
Most FHIR resources have references which relate them to other resources.
FHIR resources can reference other FHIR resources. For example, a Patient resource can reference a Practitioner resource through the generalPractitioner (opens in a new tab) property to indicate the patient's primary care provider.
The Reference data type (opens in a new tab) is used to relate resources to each other in a number of ways.
Relative references
One of the most common ways is to set only the reference
property with what the FHIR spec calls a relative URL:
{
"resourceType": "Patient",
"generalPractitioner": [
{
"reference": "Practitioner/2419a78e-4c0a-411d-b9e2-90dc081f5efa"
}
]
}
The relative URL tells us that the referenced resource is located in the same FHIR server as the referencing resource. You could fetch the Practitioner by using the Read endpoint like this:
GET https://fhir-api.zapehr.com/r4/Practitioner/2419a78e-4c0a-411d-b9e2-90dc081f5efa