The FHIR Gateway Endpoint module creates a FHIR server that acts as a proxy for one or more target FHIR servers.
The FHIR Gateway provides the benefits of a Smile CDR FHIR endpoint over top of the target servers. This includes:
_elements
and _fhirpath
parametersWhen the FHIR Gateway is placed in front of multiple target servers, it can be used to present a collection of servers as a single unified FHIR endpoint. This can be particularly useful when implementing APIs for SMART on FHIR applications, since these applications will often expect a single endpoint through which all data flows.
The FHIR Gateway is also designed to avoid revealing details about the internal FHIR servers. Internal server addresses, paging URLs, etc. are all obscured by the FHIR Gateway in its responses to clients.
Additional logging can be enabled in order to troubleshoot Gateway routing issues. See FHIR Gateway Troubleshooting Log for details.
This section lists the known limitations on this module.
$meta
, $meta-add
, $meta-delete
, $graphql
, $process-message
, $everything
, $export
, $export-poll-status
and $proxy-link
operations are supported by default. However, it is possible to add support for custom operations by configuring Custom Operation Providers.$everything
operation on instance and type level is supported only for Patient resource.DELETE Observation?status=outdated
) is NOT supported by FHIR Gateway module.PATCH
operation is NOT supported by FHIR Gateway._history
interaction is limited to the instance level.Binary
files, which is the case when target servers are HAPI-FHIR servers.As mentioned in the Consent Service documentation, Consent Service can be enabled and implemented for FHIR Gateway modules using JavaScript or Java APIs. Note though that for JavaScript implementations, the following APIs are NOT available for FHIR Gateway modules:
The gateway $export
operation supports the same options and parameters as a fhir endpoint. The urls used for status and for results have a few differences:
$export
responses, the _jobId
parameter points to a JSON Web Token (JWT), as shown below:HTTP/1.1 202 Accepted
Content-Location: http://localhost:8888/$export-poll-status?_jobId=eyJraWQiOiJmYWFhMDljNy0yNmVmLTQ3MTQtYTc3Mi1lMzYyNjllMzI1NDIiLCJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.MqSBJhODntHL0rEiDNw7cJEbScXYzQ0AYsvf40YFji2xBnxy9cG88Ft26R4P4233s6NXwp-8kCpATYUCSBviW_otBhXw8tuheKFSghgI3rcDYg6c-8cMZPALwPVhsyQGYqc4Lh7GUicWP14YsSs58edb0tt3i8w-OmmRwIFbKfLGoIgbc6Dvndf50N7UGjuzXGIV7gNeg81a5qZnlwoW_OSwEreca6ttQvqyGDxDbgcPgV5_ujbJmy7p3ETHu2i-rDRI-i9TZSd73fqRjK1lqB2GqUpwGQ67mUXD6A8cPsXWkdG-yNkHPbIJX1VBNja25F6OpNGcOS7J7QUnSHf94w.Zint-j80_YScO8OC.EtV-hmkc0y0wQdG3K6PZpw7JC9lUSjKym0w5y7eSN944bcSSXHCrv8dOxDH-IRzzG32xXgNiVZMvB0E5GeJWJE9nSbVFt6B0UzNLxy5hmEhNQ6oArN_YX8Ms2cM84RdDBLG6xauOrycjGSTl7ghPRDsi5uy-njNcwjIMY9fNeEu_baxUZkR6SngHnI_ZW0LqfC8yg-sBM029sTUamyEGgQ_VEebdAhz9Z5t7OJGKyRsqI4FwkASX04IkXR2CjoHKxvViKpdCoOz4yToUbxir0zeOT3W2q9PMF9IL2HVC-FfPfFNafvwocbUPbzbumoThGIij5vowk-EdL2qI2XM98FBE6g0hVHHUKcWrnI_jd4UTk7qFMhiq4VX4416vG3ICOfYCVabjgKfJ1oDtf9GUyC9yvvOFkcr_urVbT_QZjuqnSw.jrcH1lrUA07uLl_leSrWRA
$export-poll-status
operation returns a completed
response (status code 200), the JSON result url points to a $proxy-link
operation for each exported resource type. A GET
request must be made to this url in order to retrieve the exported resources for each type. An example response is shown below:{
"transactionTime": "2025-04-16T09:33:04.902-04:00",
"request": "http://localhost:8001/$export?_type=Patient%2CObservation&_format=json",
"requiresAccessToken": true,
"output": [
{
"type": "Observation",
"url": "http://localhost:8888/$proxy-link?_jwtId=eyJraWQiOiJmYWFhMDljNy0yNmVmLTQ3MTQtYTc3Mi1lMzYyNjllMzI1NDIiLCJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.cqSwg47f57Z43msAZdha1VvAf-W0t1V37uPdF-C8EGuJ5YzqQg8GI2_a1N2wEIpgVLXIFJQqz68mVowyegALp7Wtl0RVJcUkcsowKvfrdKMsKJaP4eqjek2x5e8qg75PETWp3aWN3Gi9azf3MvXn0FhVD9N5PNVecCfx2UeOo3kpYSrq6qSmNJha9mSoqbu5eqbQTVYbcw9yGuoM2c4Cqcsp3TqLkz8VCw--BDr9m7egK7paeN8Kr52lJIuvSdFNWwMqrerGhByBE7OsnpN5accl7o4d1RJZVCzXJJFmdjq-eZLGJsTlXzB4v6dypkfIsQRPZozdJp717pvVBUh_Ww.Xe-1tGbvOOME5Wmx.gq-qJpsJcuZ_9192-qPdJjxckbGg7Q8EhHn8wKybbKAdJDBF9NFUJh_AKoSqr8sRLGKGspoi3NB51jEn7K3Aqrq3d0tGq-xpg2zH62F9WnZ2lmFoM0jRPgbIeITePKEGsMEvt4wokjDugwm94OlX7Jhb0BgUrKWI0B7YDXe9zun_x8H8X7eFUWoNBI1tNHLYtW99aGIhAYgttpUPdF7Y__aLVJll76G_-6xug8fV0zv7GGu5WkOKMHrVW9dsysl_FIeOt51uQZW6yodOgu0YJw7AM-5RnVZj2_7jFlxOJ_lYrKALzJvDhXf-Ct5FqpZCyDITodD6De1FXI5vgcGFe3kL2glBwiMYJvhTIrn8qxaSSWC2hCrISX8ENnPXyUMyXzomAE0fnYvwBe2LviK4PImoEHjUunMA6xUj4E1hxSUHG8ThHvFLfhSLVuou7nc.5PzoIzcdQmQYQ__JBMF2fg"
},
{
"type": "Patient",
"url": "http://localhost:8888/$proxy-link?_jwtId=eyJraWQiOiJmYWFhMDljNy0yNmVmLTQ3MTQtYTc3Mi1lMzYyNjllMzI1NDIiLCJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.KxRY4HLtlEl2kW1UokT2p4cXEkIr6cPsQCyTkE4r08t5i6JyzfqCR2vUaCsNBa1QNEbf05Lyky02NMYXJ9mf62W1Y-fYwFsDHIIPy_Il4v07Xlx9fl98Cz9fidbDGWnu6EyzJPSclBjwfJ6crV2Y-9T9Tjtq78fAQrfhyKgCio7q1-pBHD1y0s7ULaaAoEAeweA7Tfv7wKIooC9W6rlPjvH_cORJGsi8zCziuHUkGAzAhKxvjB3QWHbFEZ1i_7JoDryzt5GPFGX-zIXOzXnsjsfRZN_b0aMMeQm8ntewIY7kmSXVuguuLJfIAhS5TzzHzyb7yjX_g-lUYRT1aEJAew.56k3gzui9j-HIkyC.p6sjOrmuck_XE_l2RcjohuOqLD7IDiqNyzIWueVIG8_qiJ5_yX5Bkr0v5FlQlsVz3IU_vcKTcmm8bxfrUJl4r4IpkvecY7wes_coZawecZSGH0wXzlidqwiXnVRM3-cIXmpeqgxvS1NsgucOMX1OBS4y9n-nNn6xSgYDBwVfv9Nw63r-n_shXepOGmCZU7uDYyVDrWoe9bWTgZ8gZ6cs8aDwafdMiEWvvEzopCxQPtsUX_6Yv0g6qTJZfHaJHpLVqoNFWjzgRqcvQJ9d4n2-qTnPVs21zNhXpCibS_RWh4i5jwA9n0hPpk9pJbWCSQNvSjOJg4g_MtmKmyqOGccA5TfuJ20Pp0bN7W441Haju5H91AecIt2_BnJrW37GIq6JC4ImWFZxXB5grqFTTW6wtkzlzSQnX27IYU-pew5wi_pNPxgSGwOK73TAag.-pmzZ5H_uDnxTaSatDVZdg"
}
],
"error": []
}
$proxy-link
operation as follows:GET http://localhost:8888/$proxy-link?_jwtId=eyJraWQiOiJmYWFhMDljNy0yNmVmLTQ3MTQtYTc3Mi1lMzYyNjllMzI1NDIiLCJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.KxRY4HLtlEl2kW1UokT2p4cXEkIr6cPsQCyTkE4r08t5i6JyzfqCR2vUaCsNBa1QNEbf05Lyky02NMYXJ9mf62W1Y-fYwFsDHIIPy_Il4v07Xlx9fl98Cz9fidbDGWnu6EyzJPSclBjwfJ6crV2Y-9T9Tjtq78fAQrfhyKgCio7q1-pBHD1y0s7ULaaAoEAeweA7Tfv7wKIooC9W6rlPjvH_cORJGsi8zCziuHUkGAzAhKxvjB3QWHbFEZ1i_7JoDryzt5GPFGX-zIXOzXnsjsfRZN_b0aMMeQm8ntewIY7kmSXVuguuLJfIAhS5TzzHzyb7yjX_g-lUYRT1aEJAew.56k3gzui9j-HIkyC.p6sjOrmuck_XE_l2RcjohuOqLD7IDiqNyzIWueVIG8_qiJ5_yX5Bkr0v5FlQlsVz3IU_vcKTcmm8bxfrUJl4r4IpkvecY7wes_coZawecZSGH0wXzlidqwiXnVRM3-cIXmpeqgxvS1NsgucOMX1OBS4y9n-nNn6xSgYDBwVfv9Nw63r-n_shXepOGmCZU7uDYyVDrWoe9bWTgZ8gZ6cs8aDwafdMiEWvvEzopCxQPtsUX_6Yv0g6qTJZfHaJHpLVqoNFWjzgRqcvQJ9d4n2-qTnPVs21zNhXpCibS_RWh4i5jwA9n0hPpk9pJbWCSQNvSjOJg4g_MtmKmyqOGccA5TfuJ20Pp0bN7W441Haju5H91AecIt2_BnJrW37GIq6JC4ImWFZxXB5grqFTTW6wtkzlzSQnX27IYU-pew5wi_pNPxgSGwOK73TAag.-pmzZ5H_uDnxTaSatDVZdg
Content-Type: application/fhir+ndjson
Resources from all targets are combined in the $proxy-link
ndjson
response as follows:
{"resourceType":"Patient","id":"TGT2-1331","meta":{"versionId":"1","lastUpdated":"2025-04-16T09:30:55.490-04:00","source":"#64W1IUL7HMPRcouW"},"name":[{"family":"Wilson","given":["Amanda"]}],"gender":"female","birthDate":"1974-01-13","address":[{"line":["123 Aaa St"],"city":"SomeVille1","state":"Mac","postalCode":"1234"}]}
{"resourceType":"Patient","id":"TGT2-1332","meta":{"versionId":"1","lastUpdated":"2025-04-16T09:31:03.509-04:00","source":"#nAEykunxtxGC8oYs"},"name":[{"family":"Gonzales","given":["Silvia"]}],"gender":"female","birthDate":"1978-04-23","address":[{"line":["123 Abb St"],"city":"SomeVille2","state":"Mac","postalCode":"5432"}]}
{"resourceType":"Patient","id":"TGT1-1835","meta":{"versionId":"1","lastUpdated":"2025-04-16T09:28:26.804-04:00","source":"#7X2qMH5UbaKOTY1P"},"name":[{"family":"Stevenson","given":["Jacinda"]}],"gender":"female","birthDate":"1960-05-15","address":[{"line":["123 Ccc St"],"city":"SomeVille3","state":"Mac","postalCode":"6789"}]}
{"resourceType":"Patient","id":"TGT1-1836","meta":{"versionId":"1","lastUpdated":"2025-04-16T09:28:41.954-04:00","source":"#FIWw0A09DkM9qbPh"},"name":[{"family":"Jackson","given":["John"]}],"gender":"male","birthDate":"1963-09-17","address":[{"line":["123 Ddd St"],"city":"SomeVille4","state":"Mac","postalCode":"9876"}]}
$export
routes must be defined in the operationRoutes
section of the gateway JSON configuration as shown below:
{
"operationRoutes": [
{
"id": "operatingRoute",
"resourceTypes": [
"Patient",
"Practitioner",
"Condition",
"Group"
],
"targets": [
{
"targetId": "target1"
},
{
"targetId": "target2"
}
],
"parallel": true,
"operations": [
{
"name": "$export",
"system": true,
"type": true,
"instance": true
}
]
}
]
}
Note that the $export-poll-status
and $proxy-link
operations will be automatically included when the $export
operation is used. These operations do not require explicit configuration.