A modern, robust healthcare management API built with FastAPI โ delivering secure, scalable, and efficient healthcare services with real-time notifications.
- Docker & Docker Compose
- Python 3.11+ (for local development)
cp .env.example .env # then set real passwords and SECRET_KEY
docker compose up --build -dThe API will be available at: http://localhost:8000 API Documentation: http://localhost:8000/docs
Set FIRST_ADMIN_EMAIL / FIRST_ADMIN_PASSWORD in .env to have an admin account created on first startup.
.
โโโ app/
โ โโโ api/
โ โ โโโ routes/ # API endpoint handlers
โ โ โ โโโ auth.py
โ โ โ โโโ user.py
โ โ โ โโโ patient.py
โ โ โ โโโ doctor.py
โ โ โ โโโ appointment.py
โ โ โ โโโ medical_record.py
โ โ โโโ deps.py # Auth and role dependencies
โ โโโ core/ # Core application logic
โ โ โโโ config.py # Configuration management
โ โ โโโ security.py # JWT and password hashing
โ โ โโโ cache.py # Redis response caching middleware
โ โ โโโ rate_limiter.py # Redis rate limiting middleware
โ โ โโโ notifications.py # Publishes appointment events to RabbitMQ
โ โ โโโ timeutils.py # UTC normalization
โ โโโ crud/ # Database operations layer
โ โโโ db/ # SQLAlchemy models and session
โ โโโ schemas/ # Pydantic schemas
โ โโโ tests/ # Test suites
โโโ docker-compose.yml # Multi-service orchestration
โโโ Dockerfile # API container
โโโ Dockerfile.notification # Notification worker container
โโโ notification_service.py # Async notification worker (RabbitMQ โ email)
โโโ API_EXAMPLES.http # Example requests
โโโ .env.example # Environment template
The system runs as a multi-container application. Only the API port is published; the other services are reachable on the internal network.
| Service | Purpose | Port | Health Check |
|---|---|---|---|
| app | FastAPI Application | 8000 | HTTP 200 on /health |
| notification | Email notification worker | โ | Restarts on failure |
| db | PostgreSQL Database | 5432 (internal) | pg_isready |
| redis | Cache and rate limiting | 6379 (internal) | redis-cli ping |
| rabbitmq | Message Queue | 5672 (internal) | rabbitmq-diagnostics ping |
# Production deployment
docker compose up --build -d
# View logs
docker compose logs -f app notification
# Stop services
docker compose down# Create virtual environment
python -m venv .venv
source .venv/bin/activate # Linux/Mac
# OR
.\.venv\Scripts\Activate.ps1 # Windows
# Install dependencies
pip install -r requirements-dev.txt
# Point the app at your services (or put these in .env)
export DATABASE_URL=postgresql://user:pass@localhost:5432/healthcare
export SECRET_KEY=dev-secret
# Run the application
uvicorn app.main:app --reload --host 127.0.0.1 --port 8000Redis and RabbitMQ are optional locally: caching and rate limiting fail open, and notifications are logged as errors
when RabbitMQ is unreachable. Disable them with CACHE_ENABLED=false, RATE_LIMIT_ENABLED=false and
NOTIFICATIONS_ENABLED=false.
| Command | Description |
|---|---|
docker compose up --build -d |
Build and start all services |
docker compose logs -f [service] |
Follow service logs |
docker compose down |
Stop and remove containers |
docker compose exec app [cmd] |
Execute command in app container |
| Command | Description |
|---|---|
uvicorn app.main:app --reload |
Start development server |
pytest -q |
Run test suite quietly |
pytest -v |
Run tests with verbose output |
pytest --cov=app |
Run tests with coverage |
- ๐ Secure Authentication โ JWT (HS256) bearer tokens, bcrypt password hashing
- ๐ฅ Role-Based Access Control โ Patient, Doctor, Staff and Admin roles
- ๐ Appointment Management โ Availability windows, conflict detection, free slot lookup, rescheduling and cancellation
- ๐ฉบ Medical Records โ Doctor-authored records, readable by the patient
- โก Real-time Notifications โ Appointment events published to RabbitMQ and emailed by a worker
- ๐พ Caching โ Per-user Redis response caching, invalidated on writes
- ๐ Rate Limiting โ Per-IP request throttling
- ๐ Health Checks โ Container and service health monitoring
| Prefix | Endpoints |
|---|---|
/api/auth |
POST /login, POST /register, GET /me |
/api/users |
Admin user management: list, get, update (role, active flag, linked profile) |
/api/patients |
CRUD, GET /me, GET /search?query= |
/api/doctors |
CRUD, GET /specialization/{name}, POST/DELETE /{id}/availability |
/api/appointments |
CRUD, PUT /{id}/status?status=, GET /doctor/{id}/available-slots?date= |
/api/medical-records |
CRUD, GET /patient/{patient_id} |
All scheduling times are UTC. Timestamps with an offset are converted; timestamps without one are treated as UTC.
Doctor availability is a weekly window (day_of_week 0 = Monday) and slots are 30 minutes.
User accounts link to a patient or doctor profile through reference_id.
| Role | Access |
|---|---|
| Patient | Registers publicly, creates and edits their own profile, books/reschedules/cancels their own appointments, reads their own medical records |
| Doctor | Reads patients, manages their own profile, availability and appointment statuses, creates and edits medical records |
| Staff | Manages patients, doctors and all appointments; no medical record access |
| Admin | Everything, including user management and creating non-patient accounts via /api/auth/register |
fastapi,uvicornโ Web framework and ASGI serverpydantic,pydantic-settings,email-validatorโ Validation and settingssqlalchemy,psycopg2-binaryโ ORM and PostgreSQL driverPyJWT,bcryptโ Tokens and password hashingredisโ Caching and rate limitingaio-pikaโ RabbitMQ publisher (API) and consumer (worker)aiosmtplibโ Email delivery (worker)pytest,pytest-cov,httpxโ Testing (requirements-dev.txt)
# Used by docker-compose.yml
DB_PASSWORD=your_secure_password
RABBITMQ_USER=admin
RABBITMQ_PASSWORD=your_rabbitmq_password
SECRET_KEY=your_jwt_secret_key # required when ENVIRONMENT=production
# Read by the app (compose sets these from the values above)
DATABASE_URL=postgresql://user:pass@db:5432/healthcare_db
REDIS_URL=redis://redis:6379/0
RABBITMQ_URL=amqp://user:pass@rabbitmq:5672/
ACCESS_TOKEN_EXPIRE_MINUTES=30
CACHE_ENABLED=true
RATE_LIMIT_ENABLED=true
RATE_LIMIT_PER_MINUTE=60
NOTIFICATIONS_ENABLED=true
FIRST_ADMIN_EMAIL=admin@example.com
FIRST_ADMIN_PASSWORD=change-me-please
# Notification worker (leave SMTP_SERVER empty to log emails instead of sending)
SMTP_SERVER=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=
SMTP_PASSWORD=
EMAIL_FROM=noreply@example.comapp/core/config.pyโ Centralized configuration managementdocker-compose.ymlโ Service orchestrationDockerfileโ Application container definitionDockerfile.notificationโ Worker container definition
- Copy
.env.exampleto.envand set real values - Run
docker compose up --build -d - Access API at
http://your-server:8000 - Monitor services with
docker compose logs -f
Tables are created automatically on startup. There are no migrations yet, so schema changes to an existing database must be applied manually.
- API:
GET /health - Database, Redis, RabbitMQ: automatic health checks in compose
- Multi-stage Docker builds for optimized image sizes
- Non-root user execution for enhanced security
- Connection pooling with pre-ping for database efficiency
- Request rate limiting to prevent abuse
- JWT token expiration for session security
- Password length validation (8โ72 bytes) with bcrypt hashing
Tests use a throwaway SQLite database by default and never read DATABASE_URL.
Set TEST_DATABASE_URL to run them against PostgreSQL (CI does this).
# Run all tests
pytest
# Run with coverage
pytest --cov=app --cov-report=html
# Run specific test module
pytest app/tests/test_api.py -v
# Against PostgreSQL (the database is dropped and recreated)
TEST_DATABASE_URL=postgresql://test:test@localhost:5432/test pytest- Fork the repository
- Create your feature branch
git checkout -b feature/amazing-feature
- Commit your changes
git commit -m 'Add amazing feature' - Push to the branch
git push origin feature/amazing-feature
- Open a Pull Request
This project is licensed under the MIT License.
See the LICENSE file for more information.
curl:
curl -X POST http://localhost:8000/api/appointments/ \
-H "Authorization: Bearer <token_jwt>" \
-H "Content-Type: application/json" \
-d '{
"patient_id": 1,
"doctor_id": 2,
"start_time": "2030-12-03T10:00:00",
"end_time": "2030-12-03T10:30:00",
"notes": "Consulta preventiva"
}'Python:
import requests
url = "http://localhost:8000/api/appointments/"
headers = {"Authorization": "Bearer <token_jwt>"}
payload = {
"patient_id": 1,
"doctor_id": 2,
"start_time": "2030-12-03T10:00:00",
"end_time": "2030-12-03T10:30:00",
"notes": "Consulta preventiva",
}
response = requests.post(url, json=payload, headers=headers)
print(response.status_code, response.json())See API_EXAMPLES.http for more requests.
Delivering secure, scalable healthcare APIs with cutting-edge technology.