PATCH requests in this API now follow update semantics and return 200 instead of 201. Update the feature test assertion so it validates the standardized behavior and avoids false failures.
CLQMS (Clinical Laboratory Quality Management System)
A REST API backend for modern clinical laboratory workflows.
🤖 For Claude Code
When working in this repository, prioritize Serena MCP tools for code operations:
- Use
find_symbol/get_symbols_overviewinstead ofReadfor exploring code structure - Use
replace_symbol_bodyinstead ofEditfor modifying functions, methods, classes - Use
insert_before_symbol/insert_after_symbolfor adding new code symbols - Use
search_for_patterninstead ofGrepfor searching code patterns - Use
list_dir/find_fileinstead ofGlobfor file discovery
This minimizes tool calls and leverages semantic code understanding for this PHP codebase.
CLQMS is a headless REST API backend designed to streamline laboratory operations, ensure data integrity, and manage complex diagnostic workflows. Built on a foundation of precision and regulatory compliance, this system provides comprehensive JSON endpoints for laboratory operations.
Key Characteristic: This is an API-only system with no view layer. Frontend applications (web, mobile, desktop) consume these REST endpoints to build laboratory information systems.
🏛️ Core Architecture & Design
CLQMS is a headless REST API system following a clean architecture pattern. The system is designed to be consumed by any frontend client (web, mobile, desktop) through comprehensive JSON endpoints.
API-First Architecture:
- No View Layer: This system provides REST APIs only - no HTML views, no server-side rendering
- Frontend Agnostic: Any client can consume these APIs (React, Vue, Angular, mobile apps, desktop apps)
- JSON-First: All requests/responses use JSON format
- Stateless: Each API request is independent with JWT authentication
The system is currently undergoing a strategic Architectural Redesign to consolidate legacy structures into a high-performance, maintainable schema. This design focuses on reducing technical debt and improving data consistency across:
- Unified Test Definitions: Consolidating technical, calculated, and site-specific test data.
- Reference Range Centralization: A unified engine for numeric, threshold, text, and coded results.
- Ordered Workflow Management: Precise tracking of orders from collection to verification.
🛡️ Strategic Pillars
- Precision & Accuracy: Strict validation for all laboratory parameters and reference ranges.
- Scalability: Optimized for high-volume diagnostic environments.
- Compliance: Built-in audit trails and status history for full traceability.
- Interoperability: Modular architecture designed for LIS, HIS, and analyzer integrations.
🛠️ Technical Stack
| Component | Specification |
|---|---|
| Language | PHP 8.1+ (PSR-compliant) |
| Framework | CodeIgniter 4 (API-only mode) |
| Security | JWT (JSON Web Tokens) Authorization |
| Database | MySQL (Optimized Schema Migration in progress) |
| API Format | RESTful JSON |
| Testing | PHPUnit 10.5+ |
📂 Documentation & Specifications
Key Documents
| Document | Location | Description |
|---|---|---|
| PRD | PRD.md |
Complete Product Requirements Document (API-focused) |
| Technical Guide | CLAUDE.md |
Architecture, coding standards, common commands |
| API Overview | This file | REST API documentation and endpoints |
| Database Migrations | app/Database/Migrations/ |
Database schema history |
API Documentation
All API endpoints follow REST conventions:
Base URL: /api
Authentication: JWT token required for most endpoints (except /api/login, /api/demo/*)
Response Format:
{
"status": "success|error",
"message": "Human-readable message",
"data": { ... }
}
🔌 REST API Overview
API Endpoint Categories
Authentication & Authorization
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/login |
User login, returns JWT token | No |
POST |
/api/logout |
Invalidate JWT token | Yes |
POST |
/api/refresh |
Refresh JWT token | Yes |
Patient Management
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/api/patient |
List patients with pagination | Yes |
GET |
/api/patient/{id} |
Get patient details | Yes |
POST |
/api/patient |
Create new patient | Yes |
PATCH |
/api/patient/{id} |
Update patient | Yes |
DELETE |
/api/patient/{id} |
Soft delete patient | Yes |
Order Management
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/api/ordertest |
List orders | Yes |
GET |
/api/ordertest/{id} |
Get order details | Yes |
POST |
/api/ordertest |
Create order | Yes |
PATCH |
/api/ordertest/{id} |
Update order | Yes |
DELETE |
/api/ordertest/{id} |
Delete order | Yes |
POST |
/api/ordertest/status |
Update order status | Yes |
Demo/Test Endpoints (No Auth)
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/demo/order |
Create demo order with patient | No |
Specimen Management
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/api/specimen |
List specimens | Yes |
GET |
/api/specimen/{id} |
Get specimen details | Yes |
POST |
/api/specimen |
Create specimen | Yes |
PATCH |
/api/specimen/{id} |
Update specimen | Yes |
POST |
/api/specimen/status |
Update specimen status | Yes |
Result Management
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/api/patresult |
List patient results | Yes |
GET |
/api/patresult/{id} |
Get result details | Yes |
POST |
/api/patresult |
Enter new result | Yes |
PATCH |
/api/patresult/{id} |
Update result | Yes |
POST |
/api/patresult/status |
Verify result (VER/REV/REP) | Yes |
Edge API (Instrument Integration)
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/edge/result |
Receive instrument results | API Key |
GET |
/api/edge/order |
Fetch pending orders | API Key |
POST |
/api/edge/order/{id}/ack |
Acknowledge order | API Key |
POST |
/api/edge/status |
Log instrument status | API Key |
API Response Format
All API endpoints return JSON in this format:
Success Response:
{
"status": "success",
"message": "Operation completed successfully",
"data": {
// Response data here
}
}
Error Response:
{
"status": "error",
"message": "Error description",
"errors": [
{
"field": "field_name",
"message": "Validation error message"
}
]
}
Authentication
Most endpoints require JWT authentication:
Request Headers:
Authorization: Bearer {jwt_token}
Content-Type: application/json
Login Request Example:
POST /api/login
{
"username": "labuser",
"password": "password123"
}
Login Response:
{
"status": "success",
"message": "Login successful",
"data": {
"token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"expires_in": 3600,
"user": {
"id": 1,
"username": "labuser",
"name": "Lab User"
}
}
}
Lookups Library (app/Libraries/ValueSet.php)
CLQMS uses a JSON file-based lookup system loaded via App\Libraries\Lookups class. All lookup data is stored as JSON files in app/Libraries/Data/valuesets/ for easy maintenance and versioning.
How It Works
Lookupsclass extendsValueSetwhich handles caching and file loading- Each lookup is stored as
app/Libraries/Data/valuesets/{name}.json - Lookup names are lowercase with underscores (e.g.,
gender.json,order_priority.json)
Available Lookups
| Lookup File | Description | Example Values |
|---|---|---|
gender |
Patient gender | Female, Male, Unknown |
order_priority |
Order priority levels | Stat, ASAP, Routine, Preop |
order_status |
Order lifecycle status | STC, SCtd, SArrv, SRcvd |
specimen_type |
Specimen types | BLD, SER, PLAS, UR, CSF |
specimen_status |
Specimen status | Ordered, Collected, Received |
specimen_condition |
Specimen quality flags | HEM, ITC, LIP, CLOT |
specimen_activity |
Specimen workflow events | COLLECT, RECEIVE, REJECT |
result_type |
Result data types | NMRIC, RANGE, TEXT, VSET |
result_unit |
Common measurement units | g/dL, mg/dL, x10^6/mL |
result_status |
Result validation status | Preliminary, Final, Corrected |
test_type |
Test definition types | TEST, PARAM, CALC, GROUP |
test_activity |
Test workflow activities | Order, Analyse, VER, REV |
test_status |
Test active status | Active, Inactive, Discontinued |
priority |
General priority values | STAT, HIGH, NORMAL, LOW |
race |
Ethnicity/race categories | Jawa, Sunda, Batak, etc. |
religion |
Religious affiliations | Islam, Kristen, Katolik, Hindu |
marital_status |
Marital status | Single, Married, Divorced |
death_indicator |
Death status flags | Yes, No |
identifier_type |
ID document types | KTP, Passport, SSN, SIM |
operation |
CRUD operation types | Create, Read, Update, Delete |
site_type |
Healthcare facility types | GH, PH, GHL, PHL, GL, PL |
site_class |
Facility classification | A, B, C, D, Utm, Ptm |
ws_type |
Workstation types | Primary, Secondary |
enable_disable |
Boolean toggle states | Enabled, Disabled |
entity_type |
Entity classification | Patient, Provider, Site |
requested_entity |
Requestor types | Physician, Nurse, Lab |
location_type |
Location categories | OPD, IPD, ER, LAB |
area_class |
Geographic classifications | Urban, Rural, Suburban |
adt_event |
ADT event types | Admission, Transfer, Discharge |
body_site |
Collection sites | Left Arm, Right Arm, Finger |
collection_method |
Specimen collection methods | Venipuncture, Fingerstick |
container_size |
Tube/container volumes | 3mL, 5mL, 10mL |
container_class |
Container types | Vacutainer, Tube, Cup |
container_cap_color |
Tube cap colors | Red, Purple, Blue, Green |
additive |
Tube additives | EDTA, Heparin, Fluoride |
fasting_status |
Fasting requirement flags | Fasting, Non-Fasting |
ethnic |
Ethnicity categories | Various regional groups |
math_sign |
Mathematical operators | +, -, *, /, =, <, > |
formula_language |
Formula expression types | Formula, Expression |
generate_by |
Generation methods | Auto, Manual, Import |
did_type |
Device identification types | Serial, MAC, UUID |
activity_result |
Activity outcomes | Success, Fail, Retry |
reference_type |
Reference value types | NMRIC, TEXT, LIST |
range_type |
Range calculation types | REF, CRTC, VAL, RERUN |
numeric_ref_type |
Numeric ref types | Reference, Critical, Valid |
text_ref_type |
Text reference types | Normal, Abnormal, Critical |
request_status |
Request status | Pending, Approved, Rejected |
v_category |
ValueSet categories | Various categories |
Usage
use App\Libraries\Lookups;
// Get all lookups (loads all JSON files, cached)
$allLookups = Lookups::getAll();
// Get single lookup formatted for dropdowns
$gender = Lookups::get('gender');
// Returns: [{"value":"1","label":"Female"},{"value":"2","label":"Male"},...]
// Get raw data without formatting
$raw = Lookups::getRaw('gender');
// Returns: [{"key":"1","value":"Female"},{"key":"2","value":"Male"},...]
// Get label for a specific key
$label = Lookups::getLabel('gender', '1'); // Returns 'Female'
// Get key/value pairs for select inputs
$options = Lookups::getOptions('gender');
// Returns: [["key":"1","value":"Female"],...]
// Transform database records with lookup text labels
$patients = [
['ID' => 1, 'Sex' => '1', 'Priority' => 'S'],
['ID' => 2, 'Sex' => '2', 'Priority' => 'R'],
];
$labeled = Lookups::transformLabels($patients, [
'Sex' => 'gender',
'Priority' => 'order_priority'
]);
// Result: [['ID'=>1, 'Sex'=>'1', 'SexText'=>'Female', 'Priority'=>'S', 'PriorityText'=>'Stat'],...]
// Clear cache after modifying valueset data
Lookups::clearCache();
When to Use
| Approach | Use Case |
|---|---|
| Lookups Library | Server-side static values that rarely change (gender, status, types) - fast, cached |
API /api/valueset* |
Dynamic values managed by admins at runtime, or for frontend clients needing lookup data |
Adding New Lookups
- Create
app/Libraries/Data/valuesets/{name}.json:
{
"name": "example_lookup",
"description": "Example lookup description",
"values": [
{"key": "1", "value": "Option One"},
{"key": "2", "value": "Option Two"},
{"key": "3", "value": "Option Three"}
]
}
- Access via
Lookups::get('example_lookup')
📋 Master Data Management
CLQMS provides comprehensive master data management for laboratory operations. All master data is accessible via REST API endpoints.
🧪 Laboratory Tests
The Test Definitions module manages all laboratory test configurations including parameters, calculated tests, and test panels.
Test Types
| Type Code | Description | Table |
|---|---|---|
TEST |
Individual laboratory test with technical specs | testdefsite + testdeftech |
PARAM |
Parameter value (non-lab measurement) | testdefsite + testdeftech |
CALC |
Calculated test with formula | testdefsite + testdefcal |
GROUP |
Panel/profile containing multiple tests | testdefsite + testdefgrp |
TITLE |
Section title for report organization | testdefsite |
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/tests |
List all tests with optional filtering |
GET |
/api/tests/{id} |
Get test details with type-specific data |
POST |
/api/tests |
Create new test definition |
PATCH |
/api/tests |
Update existing test |
DELETE |
/api/tests |
Soft delete test (sets EndDate) |
Filtering Parameters
TestSiteName- Search by test name (partial match)TestType- Filter by test type VID (1-5)VisibleScr- Filter by screen visibility (0/1)VisibleRpt- Filter by report visibility (0/1)
Test Response Structure
{
"status": "success",
"message": "Data fetched successfully",
"data": [
{
"TestSiteID": 1,
"TestSiteCode": "CBC",
"TestSiteName": "Complete Blood Count",
"TestType": 4,
"TypeCode": "GROUP",
"TypeName": "Group Test",
"SeqScr": 50,
"VisibleScr": 1,
"VisibleRpt": 1
}
]
}
📏 Reference Ranges
Reference Ranges define normal and critical values for test results. The system supports multiple reference range types based on patient demographics.
Reference Range Types
| Type | Table | Description |
|---|---|---|
| Numeric | refnum |
Numeric ranges with age/sex criteria |
| Text | reftxt |
Text-based reference values |
Numeric Reference Range Structure
| Field | Description |
|---|---|
NumRefType |
Type: REF (Reference), CRTC (Critical), VAL (Validation), RERUN |
RangeType |
RANGE or THOLD |
Sex |
Gender filter (0=All, 1=Female, 2=Male) |
AgeStart |
Minimum age (years) |
AgeEnd |
Maximum age (years) |
LowSign |
Low boundary sign (=, <, <=) |
Low |
Low boundary value |
HighSign |
High boundary sign (=, >, >=) |
High |
High boundary value |
Flag |
Result flag (H, L, A, etc.) |
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/refnum |
List numeric reference ranges |
GET |
/api/refnum/{id} |
Get reference range details |
POST |
/api/refnum |
Create reference range |
PATCH |
/api/refnum |
Update reference range |
DELETE |
/api/refnum |
Soft delete reference range |
📑 Value Sets
Value Sets are configurable dropdown options used throughout the system. Each Value Set Definition (VSetDef) contains multiple Value Set Values (ValueSet).
Value Set Hierarchy
valuesetdef (VSetDefID, VSName, VSDesc)
└── valueset (VID, VSetID, VValue, VDesc, VOrder, VCategory)
Common Value Sets
| VSetDefID | Name | Example Values |
|---|---|---|
| 1 | Priority | STAT (S), ASAP (A), Routine (R), Preop (P) |
| 2 | Enable/Disable | Disabled (0), Enabled (1) |
| 3 | Gender | Female (1), Male (2), Unknown (3) |
| 10 | Order Status | STC, SCtd, SArrv, SRcvd, SAna, etc. |
| 15 | Specimen Type | BLD, SER, PLAS, UR, CSF, etc. |
| 16 | Unit | L, mL, g/dL, mg/dL, etc. |
| 27 | Test Type | TEST, PARAM, CALC, GROUP, TITLE |
| 28 | Result Unit | g/dL, g/L, mg/dL, x10^6/mL, etc. |
| 35 | Test Activity | Order, Analyse, VER, REV, REP |
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/valuesetdef |
List all value set definitions |
GET |
/api/valuesetdef/{id} |
Get valueset with all values |
GET |
/api/valuesetdef/{id}/values |
Get values for specific valueset |
POST |
/api/valuesetdef |
Create new valueset definition |
PATCH |
/api/valuesetdef |
Update valueset definition |
DELETE |
/api/valuesetdef |
Delete valueset definition |
Value Set Response Structure
{
"status": "success",
"data": {
"VSetDefID": 27,
"VSName": "Test Type",
"VSDesc": "testdefsite.TestType",
"values": [
{ "VID": 1, "VValue": "TEST", "VDesc": "Test", "VOrder": 1 },
{ "VID": 2, "VValue": "PARAM", "VDesc": "Parameter", "VOrder": 2 },
{ "VID": 3, "VValue": "CALC", "VDesc": "Calculated Test", "VOrder": 3 },
{ "VID": 4, "VValue": "GROUP", "VDesc": "Group Test", "VOrder": 4 },
{ "VID": 5, "VValue": "TITLE", "VDesc": "Title", "VOrder": 5 }
]
}
}
📊 Database Tables Summary
| Category | Tables | Purpose |
|---|---|---|
| Tests | testdefsite, testdeftech, testdefcal, testdefgrp, testmap |
Test definitions |
| Reference Ranges | refnum, reftxt |
Result validation |
| Value Sets | valuesetdef, valueset |
Configurable options |
🔌 Edge API - Instrument Integration
The Edge API provides endpoints for integrating laboratory instruments via the tiny-edge middleware. Results from instruments are staged in the edgeres table before processing into the main patient results (patres).
Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/edge/result |
Receive instrument results (stored in edgeres) |
GET |
/api/edge/order |
Fetch pending orders for an instrument |
POST |
/api/edge/order/:id/ack |
Acknowledge order delivery to instrument |
POST |
/api/edge/status |
Log instrument status updates |
Workflow
Instrument → tiny-edge → POST /api/edge/result → edgeres table → [Manual/Auto Processing] → patres table
Key Features:
- Staging Table: All results land in
edgeresfirst for validation - Rerun Handling: Duplicate
SampleID+TestSiteCodeincrementsAspCntinpatres - Configurable Processing: Auto or manual processing based on settings
- Status Tracking: Full audit trail via
edgestatusandedgeacktables
📜 Usage Notice
This is an API-only backend system. There are no views, HTML templates, or server-side rendering components. Frontend applications should consume these REST endpoints to build user interfaces for laboratory operations.
This repository contains proprietary information intended for the 5Panda Team and authorized collaborators.
© 2025 5Panda Team. Engineering Precision in Clinical Diagnostics.