Open-source Electronic Health Records (EHR) platform built with Spring Boot and FHIR R4.
Ciyex EHR is a multi-tenant, FHIR-native EHR system designed for outpatient clinics and medical practices. It provides a comprehensive set of clinical, administrative, and billing features through a RESTful API.
- Clinical Documentation - Encounters, assessments, vitals, physical exams, review of systems, HPI, chief complaints, and provider notes
- Patient Management - Demographics, medical history, family history, social history, allergies, immunizations, and medications
- Scheduling - Appointments, provider schedules, slots, and recall management
- Billing & Claims - Insurance, claims, invoices, patient deposits, fee schedules, and payment processing (GPS/Stripe)
- Orders & Results - Lab orders, lab results, medication requests, procedures, and referrals
- Documents - Document management with S3 storage, PDF generation, templates, and e-signatures
- Telehealth - Video calls via Jitsi, Twilio, Cloudflare, and Telnyx integrations
- Patient Portal - Self-service registration, login, appointments, and document access
- AI Assist - Azure OpenAI and OpenAI integrations for clinical documentation
- Notifications - Email (SMTP/SendGrid) and SMS (Twilio/Telnyx)
- Multi-tenancy - Per-organization configuration with Keycloak-based tenant isolation
- FHIR R4 - Native FHIR data model using HAPI FHIR client
| Component | Technology |
|---|---|
| Language | Java 21 |
| Framework | Spring Boot 4.0.1 |
| Build | Gradle |
| Auth | Keycloak (OAuth2/OIDC) + JWT |
| Data | FHIR R4 (HAPI FHIR 8.2.1) |
| Secrets | HashiCorp Vault |
| Config | Spring Cloud Config |
| Storage | Amazon S3 |
| OpenPDF, PDFBox, OpenHTMLtoPDF | |
| Container | Docker (Eclipse Temurin 21) |
| CI/CD | GitHub Actions |
| Deployment | ArgoCD + Kustomize |
src/main/java/org/ciyex/ehr/
config/ # Security, CORS, S3, Keycloak configuration
controller/ # REST API controllers (80+)
dto/ # Data transfer objects
eligibility/ # Insurance eligibility verification
enums/ # Enumerations
exception/ # Custom exceptions
fhir/ # FHIR client service
interceptor/ # Request interceptors
security/ # JWT filters, Keycloak converters
service/ # Business logic
ai/ # AI-assisted documentation
notification/ # Email and SMS
portal/ # Patient portal auth
telehealth/ # Video call providers
storage/ # FHIR storage abstraction
util/ # Utilities
- Java 21
- Gradle 9+
- A running FHIR R4 server (e.g., HAPI FHIR)
- Keycloak instance for authentication
- HashiCorp Vault for secrets management
git clone https://github.com/ciyex-org/ciyex.git
cd ciyexThe application requires the following environment variables:
| Variable | Description |
|---|---|
VAULT_URI |
HashiCorp Vault server URL |
VAULT_TOKEN |
Vault authentication token |
CONFIG_URI |
Spring Cloud Config server URL |
CONFIG_USERNAME |
Config server username |
CONFIG_PASSWORD |
Config server password |
Application secrets (loaded from Vault):
| Secret Path | Description |
|---|---|
jwt.secret |
JWT signing key (Base64-encoded) |
spring.security.oauth2.resourceserver.jwt.issuer-uri |
Keycloak realm URL |
keycloak.auth-server-url |
Keycloak server URL |
keycloak.realm |
Keycloak realm name |
keycloak.credentials.secret |
Keycloak client secret |
keycloak.admin.username |
Keycloak admin username |
keycloak.admin.password |
Keycloak admin password |
./gradlew build -x test./gradlew bootRunThe API will be available at http://localhost:8080.
DOCKER_BUILDKIT=1 docker build -t ciyex .
docker run -p 8080:8080 \
-e VAULT_URI=https://your-vault-server \
-e VAULT_TOKEN=your-token \
-e CONFIG_URI=https://your-config-server \
-e CONFIG_USERNAME=user \
-e CONFIG_PASSWORD=pass \
ciyexFor local development without Vault and Config Server, you can override all configuration via environment variables or a local profile.
docker run -d --name ciyex-db \
-e POSTGRES_DB=ciyexdb \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-p 5432:5432 \
postgres:16docker run -d --name keycloak \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
-e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
-p 8180:8080 \
quay.io/keycloak/keycloak:26.2 start-devDATABASE_URL=jdbc:postgresql://localhost:5432/ciyexdb
DATABASE_USERNAME=postgres
DATABASE_PASSWORD=postgres
SPRING_CLOUD_VAULT_ENABLED=false
SPRING_CLOUD_CONFIG_ENABLED=false
JWT_SECRET=your-base64-encoded-secret-at-least-256-bits
KEYCLOAK_AUTH_SERVER_URL=http://localhost:8180
KEYCLOAK_REALM=master
KEYCLOAK_CREDENTIALS_SECRET=your-keycloak-client-secret
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI=http://localhost:8180/realms/mastersource .env.local
./gradlew bootRunThe API will be available at http://localhost:8080.
Set up test users in Keycloak with these roles:
| Role | Description |
|---|---|
ADMIN |
Full system access |
PROVIDER |
Clinical and administrative access |
NURSE |
Clinical documentation access |
MA |
Medical assistant access |
FRONT_DESK |
Scheduling and check-in |
BILLING |
Billing and claims access |
PATIENT |
Portal access only |
All endpoints are under /api/ and require authentication unless noted.
POST /api/auth/**- AuthenticationGET /api/public/**- Public resourcesPOST /api/portal/auth/**- Patient portal authentication
/api/encounters- Encounter management/api/vitals- Vital signs/api/assessments- Clinical assessments/api/medications- Medication management/api/lab-orders- Laboratory orders/api/lab-results- Laboratory results/api/procedures- Procedures/api/immunizations- Immunizations/api/allergies- Allergy documentation
/api/patients- Patient demographics/api/providers- Provider management/api/appointments- Scheduling/api/facilities- Facility management/api/users- User management
/api/claims- Claims management/api/invoices- Invoice management/api/gps- Payment gateway
/api/portal/**- Patient portal endpoints
The API uses a hybrid JWT authentication model:
- Keycloak (primary) - OAuth2/OIDC with RS256 JWTs from Keycloak JWKS endpoint
- Local JWT (portal) - HS256 JWTs for patient portal authentication
Role-based access:
ADMIN- Full accessPROVIDER- Clinical and administrative accessPATIENT- Portal access only
CI/CD is handled via GitHub Actions with a tag-based promotion flow:
- Push to main - Builds and pushes
<version>-alpha.<n>image to registry - Promote to RC - Retags latest alpha as
<version>-rc - Promote to GA - Retags RC as
<version>(semver)
ArgoCD Image Updater watches the registry and auto-deploys:
*-alpha.*tags to dev*-rctags to stage- Semver tags to prod
- ciyex-ehr-ui — EHR Clinical UI (Next.js)
- ciyex-portal-ui — Patient Portal (Next.js)
This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
If you modify this software and make it available over a network, you must release your source code under the same license.