A clean, extensible, and strongly typed backend service for interacting with FHIR servers using modern C# patterns and production‑grade architecture.
This project demonstrates how to build a generic, reusable, resource‑agnostic FHIR API client—the kind of foundation used in real healthcare systems where correctness, predictability, and interoperability matter.
This project was created to demonstrate how to design a clean, extensible, and strongly typed integration layer for FHIR‑based healthcare systems. The goal was to build a reusable foundation that mirrors the architectural patterns used in real-world clinical platforms, with a focus on correctness, interoperability, and long-term maintainability.
The implementation includes:
-
A generic, resource‑agnostic FHIR API client built from scratch
-
Strongly typed models for core FHIR structures such as CodeableConcept, Coding, Reference, Bundle<T>, and Observation
-
A predictable DTO layer aligned with the FHIR specification
-
Handling of real-world challenges such as variable date formats, optional fields, and nested FHIR structures
-
An architecture designed for scalability, allowing additional FHIR resource types to be added with minimal effort
-
This project highlights an architectural approach focused on clarity, reusability, and consistency—key qualities required when integrating with healthcare data systems.
This project highlights a set of architectural and engineering patterns commonly used in production‑grade FHIR integrations. It is designed to be clear, extensible, and aligned with the FHIR specification while remaining easy to adapt for additional resource types.
The project includes strongly typed, reusable models for core FHIR structures:
- CodeableConcept
- Coding
- Reference
- Bundle
- ObservationResource
These shared abstractions promote consistency, reduce duplication, and reflect the underlying patterns of the FHIR standard.
The DTO layer is intentionally structured to ensure:
- Consistent handling of optional fields
- Stable and predictable JSON shapes
- Explicit null-handling
- Preservation of FHIR naming conventions
- Strong typing without sacrificing interoperability
This approach reduces ambiguity and improves reliability when exchanging clinical data.
The architecture is designed to scale across multiple FHIR resource types through:
- Generic deserialization
- Reusable HTTP plumbing
- Extensible resource querying
- Clear separation between transport, models, and resource logic
This mirrors the patterns used in enterprise healthcare systems where flexibility and maintainability are essential.
At its current stage, this project includes example implementations for querying two FHIR resource types:
- Patient
- Observation
These examples demonstrate the architectural patterns used throughout the project, but they do not include every possible FHIR search parameter. This is intentional. In a real production environment, it is important to:
- Control which search parameters are allowed
- Prevent overly broad or unsafe queries
- Provide custom, domain‑specific error handling
- Ensure consistent validation across all incoming requests
To support this, the project uses Value Objects to encapsulate validation, parsing, and error generation. This keeps the controllers intentionally thin, allowing them to focus solely on orchestration rather than business rules or data correctness.
All validation and error handling is performed inside the Value Objects because:
- They enforce invariants at the boundary of the system
- They ensure invalid search parameters never reach the service layer
- They centralize error logic for consistency and maintainability
- They make the API predictable and easier to extend
- They allow future enhancements such as logging, auditing, or telemetry without modifying controllers
This design ensures that controllers remain lightweight while the domain layer remains expressive and strict.
The architecture is designed so that additional FHIR resources and search parameters can be added with minimal effort. Because validation lives in the Value Objects, extending the system to:
- log validation errors
- audit incoming search parameters
- enforce stricter rules
- add new resource types
can be done cleanly without modifying existing controllers or HTTP plumbing.
To test the available endpoints in this backend service, you can use the Postman collection included in the companion project:
https://github.com/jozcar1/fhir-client-js/tree/master/postman
This collection provides sample requests for creating and querying FHIR resources and is designed to work directly with this backend project. It includes example payloads and demonstrates how the frontend (or any client application) should interact with the backend rather than communicating with a FHIR server directly.
This backend is paired with a companion React + JavaScript project:
https://github.com/jozcar1/fhir-client-js
The purpose of the companion project is to showcase how a frontend application should communicate with a backend service that handles all FHIR interactions. It reinforces a key architectural principle:
Instead:
- The backend is responsible for all communication with the FHIR server
- The backend exposes controlled, secure, domain‑specific endpoints
- The frontend interacts only with the backend, never with the FHIR server
- This approach protects PHI, enforces validation rules, and ensures consistent behavior across clients.
This approach protects PHI, enforces validation rules, and ensures consistent behavior across clients.
A deliberate design choice in this project is that backend endpoints do not need to follow the FHIR REST API naming conventions.
This is intentional because:
- The backend should expose only the operations your application needs
- You can restrict or shape search parameters to match your domain
- You can provide custom validation and error handling
- You can simplify or abstract complex FHIR interactions
- You maintain full control over what the frontend is allowed to request
In other words, the backend acts as a protective façade over the FHIR server, enforcing rules, shaping data, and preventing misuse.
This project focuses on demonstrating a clean, extensible architecture for interacting with a FHIR server. However, one major component intentionally not included is production‑grade API protection.
In real healthcare systems, backend services like this are typically placed behind an API Gateway. The gateway is responsible for:
- Registering and managing client applications
- Enforcing authentication and authorization
- Supporting different access models such as:
- API keys
- SMART on FHIR (OAuth2)
- LDAP or enterprise identity providers
- Issuing or validating access tokens
The backend then receives the validated token from the gateway and uses middleware to:
- Verify the token
- Enforce access rules
- Restrict unauthorized requests
Adding this middleware layer is straightforward, and there are many established patterns and examples available in the .NET ecosystem. The omission here is intentional to keep the project focused on FHIR integration patterns rather than security infrastructure.
This separation makes it clear how the project can evolve into a production‑ready system while keeping the core FHIR logic clean, testable, and independent of authentication concerns.