Easy-to-use JSON-based REST API for OpenEMR FHIR. All code is done in classes and separate from the view to help with codebase modernization efforts. See standard OpenEMR API docs here
FHIR endpoints are defined in the primary routes file. The routes file maps an external, addressable endpoint to the OpenEMR FHIR controller which handles the request, and also handles the JSON data conversions.
"POST /fhir/Patient" => function () {
RestConfig::authorization_check("patients", "demo");
$data = (array)(json_decode(file_get_contents("php://input"), true));
return (new FhirPatientRestController())->post($data);
}
At a high level, the request processing flow consists of the following steps:
JSON Request -> FHIR Controller Component -> FHIR Validation -> Parsing FHIR Resource -> Standard Service Component -> Validation -> Database
The logical response flow begins with the database result:
Database Result -> Service Component -> FHIR Service Component -> Parse OpenEMR Record -> FHIR Controller Component -> RequestControllerHelper -> JSON Response
- FHIR API Endpoints
- FHIR Patient API
- FHIR Encounter API
- FHIR Practitioner API
- FHIR PractitionerRole API
- FHIR Immunization API
- FHIR AllergyIntolerance API
- FHIR Procedure API
- FHIR Organization API
- FHIR Observation API
- FHIR QuestionnaireResponse API
- FHIR Condition API
- FHIR MedicationRequest API
- FHIR Medication API
- FHIR Location API
- FHIR CareTeam API
- Portal FHIR API Endpoints
- Todos
Enable the Standard FHIR service (/fhir/ endpoints) in OpenEMR menu: Administration->Globals->Connectors->"Enable OpenEMR Standard FHIR REST API" Enable the Patient Portal FHIR service (/portalfhir/ endpoints) in OpenEMR menu: Administration->Globals->Connectors->"Enable OpenEMR Patient Portal FHIR REST API"
There are several ways to make API calls from an authorized session and maintain security:
- See the script at tests/api/InternalApiTest.php for examples of internal API use cases.
Standard FHIR endpoints Use http://localhost:8300/apis/fhir as base URI.
Example: http://localhost:8300/apis/fhir/Patient
returns a Patient's bundle resource, etc
The OpenEMR FHIR API utilizes the OAuth2 password credential flow for authentication. To obtain an API token, submit your login credentials and requested scope. The scope must match a site that has been setup in OpenEMR, in the /sites/ directory. If additional sites have not been created, set the scope to 'default'.
Request:
curl -X POST -H 'Content-Type: application/json' 'http://localhost:8300/apis/fhir/auth' \
-d '{
"grant_type":"password",
"username": "ServiceUser",
"password": "password",
"scope":"site id"
}'
Response:
{
"token_type": "Bearer",
"access_token": "eyJ0b2tlbiI6IjAwNmZ4TWpsNWhsZmNPelZicXBEdEZVUlNPQUY5KzdzR1Jjejc4WGZyeGFjUjY2QlhaaEs4eThkU3cxbTd5VXFBeTVyeEZpck9mVzBQNWc5dUlidERLZ0trUElCME5wRDVtTVk5bE9WaE5DTHF5RnRnT0Q0OHVuaHRvbXZ6OTEyNmZGUmVPUllSYVJORGoyZTkzTDA5OWZSb0ZRVGViTUtWUFd4ZW5cL1piSzhIWFpJZUxsV3VNcUdjQXR5dmlLQXRXNDAiLCJzaXRlX2lkIjoiZGVmYXVsdCIsImFwaSI6Im9lbXIifQ==",
"expires_in": "3600",
"user_data": {
"user_id": "1"
}
}
The Bearer token is required for each OpenEMR API request, and is conveyed using an Authorization header.
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Patient' \
-H 'Authorization: Bearer eyJ0b2tlbiI6IjAwNnZ3eGJZYmFrOXlxUjF4U290Y1g4QVVDd3JOcG5yYXZEaFlqaHFjWXJXRGNDQUtFZmJONkh2cElTVkJiaWFobHBqOTBYZmlNRXpiY2FtU01pSHk1UzFlMmgxNmVqZEhcL1ZENlNtaVpTRFRLMmtsWDIyOFRKZzNhQmxMdUloZmNJM3FpMGFKZ003OXdtOGhYT3dpVkx5b3BFRXQ1TlNYNTE3UW5TZ0dsUVdQbG56WjVxOVYwc21tdDlSQ3RvcDV3TEkiLCJzaXRlX2lkIjoiZGVmYXVsdCIsImFwaSI6ImZoaXIifQ=='
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Patient'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Patient/90a8923c-0b1c-4d0a-9981-994b143381a7'
- Supported Search Parameters
- address
- address-city
- address-postalcode
- address-state
- birthdate
- family
- gender
- given
- name
- phone
- telecom
Request:
curl -X POST -H 'Content-Type: application/fhir+json' 'http://localhost:8300/apis/fhir/Patient' -d \
'{
"resourceType": "Patient",
"identifier": [ { "system": "urn:oid:1.2.36.146.595.217.0.1", "value": "12345" } ],
"name": [ {
"family": "Chalmers",
"given": [ "Peter", "James" ]
} ],
"gender": "male",
"birthDate": "1974-12-25"
}'
Request:
curl -X PUT -H 'Content-Type: application/fhir+json' 'http://localhost:8300/apis/fhir/Patient/90a8923c-0b1c-4d0a-9981-994b143381a7' -d \
'{
"resourceType": "Patient",
"id": "1",
"identifier": [ { "system": "urn:oid:1.2.36.146.595.217.0.1", "value": "12345" } ],
"name": [ {
"family": "Chalmers",
"given": [ "Peter", "James" ]
} ],
"gender": "male",
"birthDate": "1974-01-13",
"address": [ {
"line": [ "534 Erewhon St" ],
"city": "PleasantVille",
"state": "Vic",
"postalCode": "3999"
} ]
}'
Request:
curl -X PATCH -H 'Content-Type: application/fhir+json' 'http://localhost:8300/apis/fhir/Patient/90a8923c-0b1c-4d0a-9981-994b143381a7' -d \
'[
{
"op": "replace",
"path": "/address/0/postalCode",
"value": "M5C 2X8"
},
{
"op": "replace",
"path": "/birthDate",
"value": "1974-02-13"
}
]'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Encounter'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Encounter/90c196f2-51cc-4655-8858-3a80aebff3ef'
- Supported Search Parameters
- _id
- patient
- date {gt|lt|ge|le}
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Practitioner'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Practitioner/90a8923c-0b1c-4d0a-9981-994b143381a7'
- Supported Search Parameters
- address
- address-city
- address-postalcode
- address-state
- active
- family
- given
- name
- phone
- telecom
Request:
curl -X POST -H 'Content-Type: application/fhir+json' 'http://localhost:8300/apis/fhir/Practitioner' -d \
'{
"resourceType": "Practitioner",
"identifier": [ { "system": "http://hl7.org/fhir/sid/us-npi", "value": "1122334499" } ],
"name": [ {
"use": "official",
"family": "Chalmers",
"given": [ "Peter", "James" ]
} ]
}'
Request:
curl -X PATCH -H 'Content-Type: application/fhir+json' 'http://localhost:8300/apis/fhir/Practitioner/90a8923c-0b1c-4d0a-9981-994b143381a7' -d \
'{
"resourceType": "Practitioner",
"identifier": [ { "system": "http://hl7.org/fhir/sid/us-npi", "value": "1155667799" } ],
"name": [ {
"use": "official",
"family": "Theil",
"given": [ "Katy", "Wilson" ]
} ],
"address": [ {
"line": [ "534 Erewhon St" ],
"city": "PleasantVille",
"state": "Vic",
"postalCode": "3999"
} ]
}'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/PractitionerRole'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/PractitionerRole/90de091a-91e9-4bbe-9a81-75ed623f65bf'
- Supported Search Parameters
- speciality
- practitioner
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Immunization'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Immunization/90feaaa2-4097-4437-966e-c425d1958dd6'
- Supported Search Parameters
- patient
Request:
curl -X GET 'http://localhost:8300/apis/fhir/AllergyIntolerance'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/AllergyIntolerance//90feaaa2-4097-4437-966e-c425d1958dd6'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Organization'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Organization/1'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Observation'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Observation/9150635b-0705-4a27-8820-df8b56cf07eb'
Request:
curl -X POST -H 'Content-Type: application/fhir+json' 'http://localhost:8300/apis/fhir/QuestionnaireResponse' -d \
'{
"resourceType": "QuestionnaireResponse",
"id": "697485",
"meta": {
"versionId": "1",
"lastUpdated": "2020-03-22T09:11:45.181+00:00",
"source": "#L0otRLyoImuOVD2S"
},
"status": "completed",
"item": [ {
"linkId": "1",
"text": "Do you have allergies?"
}, {
"linkId": "2",
"text": "General questions",
"item": [ {
"linkId": "2.1",
"text": "What is your gender?"
}, {
"linkId": "2.2",
"text": "What is your date of birth?"
}]
}]
} ]
}'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Condition'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Condition/9109890a-6756-44c1-a82d-bdfac91c7424'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Procedure'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Procedure/9109890a-6756-44c1-a82d-bdfac91c7424'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/MedicationRequest'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/MedicationRequest/9128a1ec-95be-4649-8a66-d3686b7ab0ca'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Medication'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Medication/9109890a-6756-44c1-a82d-bdfac91c7424'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Location'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/Location/90f3d0e9-2a19-453b-84bd-1fa2b533f96c'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/CareTeam'
Request:
curl -X GET 'http://localhost:8300/apis/fhir/CareTeam/915e8fb4-86b2-4365-a420-d46fc07d5aed'
OpenEMR patient portal fhir endpoints Use http://localhost:8300/apis/portalfhir as base URI.
Example: http://localhost:8300/apis/portalfhir/Patient
returns a resource of the patient.
The OpenEMR Patient Portal FHIR service utilizes the OAuth2 password credential flow for authentication. To obtain an API token, submit your login credentials and requested scope. The scope must match a site that has been setup in OpenEMR, in the /sites/ directory. If additional sites have not been created, set the scope
to 'default'. If the patient portal is set to require email address on authenticate, then need to also include an email
field in the request.
Request:
curl -X POST -H 'Content-Type: application/json' 'http://localhost:8300/apis/portalfhir/auth' \
-d '{
"grant_type":"password",
"username": "ServiceUser",
"password": "password",
"scope":"site id"
}'
Response:
{
"token_type": "Bearer",
"access_token": "eyJ0b2tlbiI6IjAwNmZ4TWpsNWhsZmNPelZicXBEdEZVUlNPQUY5KzdzR1Jjejc4WGZyeGFjUjY2QlhaaEs4eThkU3cxbTd5VXFBeTVyeEZpck9mVzBQNWc5dUlidERLZ0trUElCME5wRDVtTVk5bE9WaE5DTHF5RnRnT0Q0OHVuaHRvbXZ6OTEyNmZGUmVPUllSYVJORGoyZTkzTDA5OWZSb0ZRVGViTUtWUFd4ZW5cL1piSzhIWFpJZUxsV3VNcUdjQXR5dmlLQXRXNDAiLCJzaXRlX2lkIjoiZGVmYXVsdCIsImFwaSI6Im9lbXIifQ==",
"expires_in": "3600",
"user_data": {
"user_id": "1"
}
}
The Bearer token is required for each OpenEMR Patient Portal FHIR service request, and is conveyed using an Authorization header.
Request:
curl -X GET 'http://localhost:8300/apis/portalfhir/Patient' \
-H 'Authorization: Bearer eyJ0b2tlbiI6IjAwNmZ4TWpsNWhsZmNPelZicXBEdEZVUlNPQUY5KzdzR1Jjejc4WGZyeGFjUjY2QlhaaEs4eThkU3cxbTd5VXFBeTVyeEZpck9mVzBQNWc5dUlidERLZ0trUElCME5wRDVtTVk5bE9WaE5DTHF5RnRnT0Q0OHVuaHRvbXZ6OTEyNmZGUmVPUllSYVJORGoyZTkzTDA5OWZSb0ZRVGViTUtWUFd4ZW5cL1piSzhIWFpJZUxsV3VNcUdjQXR5dmlLQXRXNDAiLCJzaXRlX2lkIjoiZGVmYXVsdCIsImFwaSI6Im9lbXIifQ=='
Request:
curl -X GET 'http://localhost:8300/apis/portalfhir/Patient'