Skip to main content
Version: v0.1.0

REST API Reference

Complete reference for the Ciyex EHR REST API.

Overview

The Ciyex EHR REST API provides programmatic access to all platform features. The API follows RESTful principles and uses JSON for request and response bodies.

Base URL

Development: http://localhost:8080
Staging: https://api-stage.example.com
Production: https://api.example.com

Authentication

All API requests require authentication using JWT tokens.

Get Access Token

POST /api/auth/login
Content-Type: application/json

{
"username": "user@example.com",
"password": "password123"
}

Response:

{
"success": true,
"message": "Login successful",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 3600,
"user": {
"id": 123,
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"role": "PROVIDER"
}
}
}

Using the Token

Include the token in the Authorization header:

GET /api/patients
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Refresh Token

POST /api/auth/refresh
Content-Type: application/json

{
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Response Format

All API responses follow this structure:

Success Response

{
"success": true,
"message": "Operation completed successfully",
"data": {
// Response data
}
}

Error Response

{
"success": false,
"message": "Error description",
"error": {
"code": "ERROR_CODE",
"details": "Detailed error message"
}
}

HTTP Status Codes

CodeMeaningDescription
200OKRequest successful
201CreatedResource created successfully
400Bad RequestInvalid request parameters
401UnauthorizedMissing or invalid authentication
403ForbiddenInsufficient permissions
404Not FoundResource not found
409ConflictResource conflict (duplicate)
422Unprocessable EntityValidation error
500Internal Server ErrorServer error

Pagination

List endpoints support pagination:

GET /api/patients?page=0&size=20&sort=lastName,asc

Parameters:

  • page - Page number (0-indexed)
  • size - Items per page (default: 20, max: 100)
  • sort - Sort field and direction (e.g., lastName,asc)

Response:

{
"success": true,
"data": {
"content": [...],
"pageable": {
"pageNumber": 0,
"pageSize": 20
},
"totalElements": 150,
"totalPages": 8,
"last": false,
"first": true
}
}

Filtering

Use query parameters for filtering:

GET /api/patients?firstName=John&status=ACTIVE

API Endpoints

Authentication

Login

POST /api/auth/login

Keycloak Login

POST /api/auth/keycloak-login

Logout

POST /api/auth/logout

Refresh Token

POST /api/auth/refresh

Patients

List Patients

GET /api/patients

Get Patient

GET /api/patients/{id}

Create Patient

POST /api/patients

Update Patient

PUT /api/patients/{id}

Delete Patient

DELETE /api/patients/{id}

Search Patients

GET /api/patients/search?q={query}

Appointments

List Appointments

GET /api/appointments

Get Appointment

GET /api/appointments/{id}

Create Appointment

POST /api/appointments

Update Appointment

PUT /api/appointments/{id}

Cancel Appointment

POST /api/appointments/{id}/cancel

Get Available Slots

GET /api/appointments/available-slots?providerId={id}&date={date}

Providers

List Providers

GET /api/providers

Get Provider

GET /api/providers/{id}

Get Provider Schedule

GET /api/providers/{id}/schedule?startDate={date}&endDate={date}

Encounters

List Encounters

GET /api/encounters

Get Encounter

GET /api/encounters/{id}

Create Encounter

POST /api/encounters

Update Encounter

PUT /api/encounters/{id}

Clinical Data

Add Vitals

POST /api/patients/{patientId}/vitals

Add Lab Results

POST /api/patients/{patientId}/lab-results

Add Condition

POST /api/patients/{patientId}/conditions

Add Allergy

POST /api/patients/{patientId}/allergies

Add Medication

POST /api/patients/{patientId}/medications

Documents

Upload Document

POST /api/patients/{patientId}/documents
Content-Type: multipart/form-data

List Documents

GET /api/patients/{patientId}/documents

Download Document

GET /api/documents/{documentId}/download

Delete Document

DELETE /api/documents/{documentId}

Telehealth

Create Room

POST /api/telehealth/rooms

Join Room

POST /api/telehealth/jitsi/join

Billing

Create Invoice

POST /api/billing/invoices

List Invoices

GET /api/billing/invoices

Process Payment

POST /api/billing/payments

Messages

Send Message

POST /api/messages

List Messages

GET /api/messages

Mark as Read

PUT /api/messages/{id}/read

Rate Limiting

API requests are rate-limited to prevent abuse:

  • Authenticated requests: 1000 requests per hour
  • Unauthenticated requests: 100 requests per hour

Rate limit headers:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1634567890

Webhooks

Subscribe to events via webhooks:

Available Events

  • patient.created
  • patient.updated
  • appointment.created
  • appointment.updated
  • appointment.cancelled
  • encounter.created
  • invoice.created
  • payment.received

Register Webhook

POST /api/webhooks
Content-Type: application/json

{
"url": "https://your-app.com/webhook",
"events": ["appointment.created", "appointment.cancelled"],
"secret": "your-webhook-secret"
}

Webhook Payload

{
"event": "appointment.created",
"timestamp": "2024-10-15T10:30:00Z",
"data": {
"id": 123,
"patientId": 456,
"providerId": 789,
"appointmentDate": "2024-10-20",
"appointmentTime": "10:00:00"
}
}

Error Codes

CodeDescription
AUTH_001Invalid credentials
AUTH_002Token expired
AUTH_003Insufficient permissions
VAL_001Validation error
VAL_002Missing required field
RES_001Resource not found
RES_002Resource already exists
SYS_001Internal server error
SYS_002Database error

Code Examples

JavaScript/TypeScript

// Login
const login = async (username: string, password: string) => {
const response = await fetch('http://localhost:8080/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password })
});

const data = await response.json();
localStorage.setItem('token', data.data.token);
return data;
};

// Get patients
const getPatients = async () => {
const token = localStorage.getItem('token');
const response = await fetch('http://localhost:8080/api/patients', {
headers: { 'Authorization': `Bearer ${token}` }
});

return await response.json();
};

// Create patient
const createPatient = async (patientData) => {
const token = localStorage.getItem('token');
const response = await fetch('http://localhost:8080/api/patients', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(patientData)
});

return await response.json();
};

Python

import requests

# Login
def login(username, password):
response = requests.post(
'http://localhost:8080/api/auth/login',
json={'username': username, 'password': password}
)
data = response.json()
return data['data']['token']

# Get patients
def get_patients(token):
response = requests.get(
'http://localhost:8080/api/patients',
headers={'Authorization': f'Bearer {token}'}
)
return response.json()

# Create patient
def create_patient(token, patient_data):
response = requests.post(
'http://localhost:8080/api/patients',
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
},
json=patient_data
)
return response.json()

cURL

# Login
curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"user@example.com","password":"password123"}'

# Get patients
curl -X GET http://localhost:8080/api/patients \
-H "Authorization: Bearer YOUR_TOKEN"

# Create patient
curl -X POST http://localhost:8080/api/patients \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"identification": {
"firstName": "John",
"lastName": "Doe",
"dateOfBirth": "1985-06-15",
"gender": "Male"
},
"contact": {
"email": "john.doe@example.com",
"phoneNumber": "555-123-4567"
}
}'

Testing

Postman Collection

Download the Postman collection:

https://github.com/ciyex-org/ciyex/blob/main/postman/Ciyex-API.postman_collection.json

Swagger/OpenAPI

Access interactive API documentation:

http://localhost:8080/swagger-ui.html

Best Practices

  1. Always use HTTPS in production
  2. Store tokens securely - Use httpOnly cookies or secure storage
  3. Implement token refresh - Refresh before expiration
  4. Handle errors gracefully - Check response status and error codes
  5. Respect rate limits - Implement exponential backoff
  6. Validate input - Validate data before sending
  7. Use pagination - Don't fetch all records at once
  8. Cache responses - Cache when appropriate

Next Steps