FHIR integration
FHIR R4 endpoints, authentication, supported resources, operations, search parameters, and request examples.
Xenrad exposes a FHIR R4 JSON API for site-scoped clinical data. Authentication uses SMART-style access tokens from the OAuth2 token endpoint. There is no separate “FHIR user”; the integration client is bound to a site and the token’s claims determine what you can do.
Standards
- FHIR version: R4 (normative
4.0.1in the capability statement) - Format:
application/fhir+json(JSON). This guide uses that format in examples. - Auth: Bearer access tokens; scopes are SMART system style (
system/Resource.readorsystem/Resource.write).
Before you start
- Create an API key and register JWKS.
- Allow the scopes you need (at minimum read or write for each resource you will touch).
- Request tokens with
audience=xenrad-fhir(recommended) and ensure the issued token is accepted by the FHIR service (itsaudmust bexenrad-fhir).
Base URL — use the FHIR base URL your organization or hosting team provides (HTTPS in production). It is a different host or path from the staff web app. See Endpoints reference for how it relates to OAuth2 and paths.
Step 1 — Verify capability and SMART metadata
-
SMART configuration (OAuth2 host):
GET /.well-known/smart-configuration
Usetoken_endpointfrom this document to obtain access tokens (same host as in OAuth guide). -
Capability statement:
GET /fhir/metadataon the FHIR host. Confirms the server supports the listed resource types and interactions.
DELETE is not supported for the clinical resources listed below.
Step 2 — Obtain an access token
Follow OAuth2, API keys, and client assertions. Minimum points specific to FHIR:
scopemust list eachsystem/…scope you will use, space-separated, for example:
system/Patient.read system/Observation.read- Pass
audience=xenrad-fhirin the form body (recommended).
Step 3 — Call FHIR
Send:
Authorization: Bearer <access_token>
Accept: application/fhir+json
Content-Type: application/fhir+json # for POST/PUTURL patterns
| Operation | Method | Path |
|---|---|---|
| Search | GET | /fhir/{ResourceType}?{search} |
| Read | GET | /fhir/{ResourceType}/{id} |
| Create | POST | /fhir/{ResourceType} |
| Update | PUT | /fhir/{ResourceType}/{id} |
The server enforces a read or write system/Resource scope for the resource in the request path and method: create and update need .write; read and search need .read.
Supported resources and typical use
| Resource | Use cases |
|---|---|
| Patient | Master demographics, identifiers, contact points. |
| Condition | Problem list, clinical status, coded conditions. |
| AllergyIntolerance | Allergies, clinical and verification status. |
| Observation | Lab or clinical observations coded or textual. |
| Procedure | Documented procedures. |
| DiagnosticReport | Read structured radiology or clinical reports (backed by internal reports). |
| DocumentReference | Document metadata (and content pointers your mapping supports). |
Search parameters (implemented)
The server’s search support is intentionally lean; it covers common filters. Parameters below are the ones the implementation recognizes.
Patient — GET /fhir/Patient?…
| Parameter | Matches |
|---|---|
identifier | Internal business identifier (maps to the patient’s identifier field for the site). |
name | Case-insensitive substring of patient name. |
birthdate | Date of birth (exact match to stored value for the field). |
gender | Administrative gender. |
If no query parameters are present, the search returns all patients in the site attached to the token.
Condition — GET /fhir/Condition?…
| Parameter | Notes |
|---|---|
patient | Reference, for example Patient/{uuid}. The id is the Xenrad id. |
clinical-status | Filter by stored clinical status text/code path your deployment uses. |
code | Filter on coded code field. |
AllergyIntolerance — GET /fhir/AllergyIntolerance?…
Same style as conditions: patient, clinical-status, code.
Observation / Procedure
| Parameter | Notes |
|---|---|
patient | Patient/{id} |
code | Coded field filter |
DocumentReference
| Parameter | Notes |
|---|---|
patient | Patient/{id} |
type | Document type code (doc_type_code path internally). |
DiagnosticReport
| Parameter | Notes |
|---|---|
patient | Resolves to reports whose study belongs to the patient. |
status | Use final to map to completed reports, other values to draft. |
Bundle search responses are JSON FHIR Bundle resources with type: searchset.
Create and update semantics
- POST — creates a new resource; the server assigns an
idin Xenrad. - PUT — id in path must match an existing id for the site, or the server will treat according to its implementation of upsert (for patients, a body without id creates when permitted).
Patient JSON mapping highlights for writes:
name[0].textfor display nameidentifier[0].valuefor the business identifiertelecomfor phone/email bysystemaddress[0]fortext,state,country,postalCodegender,birthDateISO
Other resources expect references like Patient/{id} in subject / patient fields consistent with your payload examples; follow validation errors the API returns in OperationOutcome.
Read by id
GET /fhir/Patient/{id} returns a single Patient if it belongs to the token’s site; 404 style OperationOutcome if not (exact behavior uses FHIR OperationOutcome in JSON).
Error format
On failure, responses use FHIR OperationOutcome (for example 404/405/500 paths) with machine-readable issue entries. Read diagnostics for developer clues.
Example: token + Patient search (outline)
POSTtoken endpoint with client assertion,scope=system/Patient.read,audience=xenrad-fhir.GET {fhirBase}/fhir/Patient?name=smithwithAuthorization: Bearer ….
Related
- HL7 — v2 events that may feed the same patient data.
- Endpoints reference — which host to call in each environment.
- OAuth2 — JWKS, scopes, audiences.