Connecting to External FHIR Servers
CLI connections to external FHIR servers is in Beta. Please join us on Discord with questions or email hello@medplum.com.
When building an application, you many need to query or write data to an external FHIR server as part of your application's workflow. For example:
- When a new patient is created, see if that patient already exists in another server
- When an encounter is finalized, synchronize the encounter documentation to another FHIR server
- On a bi-weekly basis, pull new FHIR data from a partner using a Bulk FHIR API
To enable these scenarios, you will need a clientId
or clientSecret
to access the system you want to connect to. Please note that different systems have different levels of functionality, and so the commands in the CLI are not guaranteed to work.
The examples below use the CLI optional flags.
Setting up your credentials
Medplum CLI stores credentials to be used in a future period without needing it to be entered in every command. By using the profile
command, this helps with the ability to work with multiple FHIR servers.
Setting a Profile
In this example, we will set up a profile using medplum profile set <profileName>
with the flags below:
- --auth-type
- --client-id
- --client-secret
- --base-url
- --token-url
- --authorize-url
- --fhir-url-path
Syntax
medplum profile set <profileName> \
--auth-type <auth-type> \
--base-url <base-url> \
--fhir-url-path <fhir-url-path> \
--token-url <token-url> \
--client-id <client-id> \
--client-secret <client-secret>
Accepted Auth Type |
---|
basic |
client-credentials |
authorization-code |
jwt-bearer |
The profile will now be stored in a file directory in ~.medplum/<profileName>.json
Once you have a profile, you can connect with external FHIR servers with your profile using the -p
flag.
Example: Basic Auth
medplum profile set example \
--auth-type "basic" \
--base-url "https://api.example.com" \
--fhir-url-path "fhir/R4" \
--client-id "MY_CLIENT_ID" \
--client-secret "MY_CLIENT_SECRET"
Example: JWT Bearer
medplum profile set example \
--auth-type "jwt-bearer" \
--base-url "https://api.example.com" \
--fhir-url-path "fhir/R4" \
--token-url "/oauth2/token" \
--client-id "MY_CLIENT_ID" \
--client-secret "MY_CLIENT_SECRET"
--scope "openid profile"
--audience "/oauth2/token"
--subject "john_doe"
--issuer "api.example.com"
Example: JWT Assertion
medplum profile set example \
--auth-type "jwt-assertion" \
--base-url "https://api.example.com" \
--fhir-url-path "fhir/R4" \
--token-url "/oauth2/token" \
--client-id "MY_CLIENT_ID" \
--audience "/oauth2/token" \
--subject "john_doe" \
--private-key-path "/path/to/privatekey.pem"
If you are authenticating with Epic and it returns \{"error":"invalid_client","error_description":null\}
, here is a Doc to Troubleshoot.
Example: Client Credentials
medplum profile set example \
--auth-type "client-credentials" \
--base-url "https://api.example.com" \
--fhir-url-path "fhir/R4" \
--token-url "oauth2/token" \
--client-id "MY_CLIENT_ID" \
--client-secret "MY_CLIENT_SECRET"
Example: User Login / Authorization Code
medplum profile set example \
--base-url "https://api.example.com" \
--fhir-url-path "fhir/R4" \
--authorize-url "oauth2/authorize" \
--token-url "oauth2/token"
Other profile commands include:
describe
To see the state of your credentials in on profile
Syntax
medplum profile describe example
Example
medplum profile describe <profileName>
remove
Removing a profile
Syntax
medplum profile remove <profileName>
Example
medplum profile remove example
list
To see all of your profiles
medplum profile list
After your profiles are set, you can login with your credentials and use them on future commands. To login:
medplum login --profile <profile>
For more information take a look at our CLI login
Logging in with a new Profile
You can run medplum login --profile <profile>
and set the same flags that profile has to set a profile and automatically login
Example: Logging in with JWT Bearer
medplum login \
--profile "example" \
--auth-type "jwt-bearer" \
--base-url "https://api.example.com" \
--fhir-url-path "fhir/R4" \
--token-url "/oauth2/token" \
--client-id "MY_CLIENT_ID" \
--client-secret "MY_CLIENT_SECRET"
--scope "openid profile"
--audience "/oauth2/token"
--subject "john_doe"
--issuer "api.example.com"
When running medplum login --profile <profile>
, all of the flags need to be set with the flags and valid data
Example: Basic search
In this example, we will show how to search for a patient by identifier using the command line after a profile has been set.
medplum get -p <profileName> 'Patient?identifier:contains=3SH0A00AA00'
Example: Create encounter
In this example, an Encounter is created in another system using the command line after a profile has been set.
medplum post -p <profileName> Encounter '{"resourceType": "Encounter", "status": "finished", "class": {"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "AMB"}, "type": [{"coding": [{"system": "http://snomed.info/sct", "code": "162673000", "display": "General examination of patient (procedure)"}], "text": "General examination of patient (procedure)"}], "subject": {"reference": "Patient/13e44a47-636b-49e2-adb3-9f19c7e0e47a", "display": "Mr. Dustin31 Ritchie586"}}'
Example: Bulk FHIR Export
In this example, Bulk FHIR ndjson files are exported from the server and stored on on the local drive after a profile has been set.
medplum bulk export -p <profileName> -e Group/all
For example, CMS BCDA publishes a Bulk FHIR test server. You can store test credentials here in a profile and try the following command.
medplum profile set bcda-sandbox --base-url https://sandbox.bcda.cms.gov --fhir-url-path api/v2/ --token-url https://sandbox.bcda.cms.gov/auth/token --client-id <client-id> --client-secret <client-secret>
And then run
medplum bulk export -p bcda-sandbox -e Group/all
Next Steps
The Medplum CLI uses Medplum TypescriptSDK to power the functionality. Once the external connection is working and you have tested some of the basic scenarios, it is recommended to build out your integration as a bot to enable your event driven or cron-based workflow.