Pharmacy
Search the drug catalog, dispense medications against prescriptions, process returns, and check real-time stock levels. The Pharmacy module runs on the ERP Service and uses the same batch tracking and inventory engine as Katasticho ERP — ensuring consistent stock management, expiry tracking, and audit trails across the hospital.
Base URL
https://hospital.katixo.com/api/v1
Endpoints
GET/api/v1/pharmacy/drugs
POST/api/v1/pharmacy/dispense
GET/api/v1/pharmacy/dispense
GET/api/v1/pharmacy/dispense/{dispenseId}
POST/api/v1/pharmacy/returns
GET/api/v1/pharmacy/stock
Authentication: All endpoints require a valid JWT Bearer token in the Authorization header. All IDs are UUIDs.
Drug categories
| Category | Description |
|---|
TABLET | Oral solid dosage forms (e.g. Paracetamol 500mg, Azithromycin 250mg). |
CAPSULE | Capsule dosage forms (e.g. Omeprazole 20mg, Amoxicillin 500mg). |
SYRUP | Liquid oral preparations (e.g. Cough Syrup, Lactulose Solution). |
INJECTION | Injectable preparations (e.g. Ceftriaxone 1g IV, Insulin 40IU/ml). |
OINTMENT | Topical preparations (e.g. Betadine Ointment, Mupirocin 2%). |
DROPS | Eye, ear, or nasal drops (e.g. Moxifloxacin Eye Drops, Otrivin Nasal Drops). |
Dispensing statuses
| Status | Description |
|---|
PENDING | Prescription received but drugs not yet dispensed to the patient. |
DISPENSED | Drugs have been dispensed to the patient. Stock has been deducted. |
RETURNED | Dispensed drugs have been returned (partially or fully). Stock has been restored. |
Search drug catalog
GET/api/v1/pharmacy/drugs
Search and browse the drug catalog. Returns a paginated list of drugs with their category, composition, and pricing. The response is wrapped in ApiResponse<PagedResponse<DrugResponse>>.
Query parameters
| Parameter | Type | Description |
|---|
search | String | Free-text search across drug name, generic name, and composition. |
category | String | Filter by category: TABLET, CAPSULE, SYRUP, INJECTION, OINTMENT, DROPS. |
page | int | Page number (zero-based, default: 0). |
size | int | Results per page (default: 20). |
curl "https://hospital.katixo.com/api/v1/pharmacy/drugs?search=paracetamol&category=TABLET&page=0&size=10" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
# Response
{
"success": true,
"message": "Drugs retrieved successfully",
"data": {
"content": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Paracetamol 500mg",
"genericName": "Paracetamol",
"category": "TABLET",
"composition": "Paracetamol IP 500mg",
"manufacturer": "Cipla Ltd",
"mrp": 25.50,
"sellingPrice": 22.00,
"hsnCode": "30049099",
"gstRate": 12.00,
"scheduleType": "OTC",
"isActive": true
},
{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"name": "Paracetamol 650mg",
"genericName": "Paracetamol",
"category": "TABLET",
"composition": "Paracetamol IP 650mg",
"manufacturer": "GSK Pharmaceuticals",
"mrp": 32.00,
"sellingPrice": 28.50,
"hsnCode": "30049099",
"gstRate": 12.00,
"scheduleType": "OTC",
"isActive": true
}
],
"page": 0,
"size": 10,
"totalElements": 2,
"totalPages": 1,
"last": true
},
"errors": null
}
Dispense drugs
POST/api/v1/pharmacy/dispense
Dispenses drugs against a prescription. Stock is deducted from the specified batches and the dispensing record is linked to the patient and prescription. Returns 201 Created on success.
Request body
| Field | Type | Required | Description |
|---|
prescriptionId | UUID | Yes | ID of the OPD/IPD prescription to dispense against. |
items | DispenseItemRequest[] | Yes | At least one item to dispense. See item fields below. |
DispenseItemRequest fields
| Field | Type | Required | Description |
|---|
drugId | UUID | Yes | ID of the drug from the drug catalog. |
batchId | UUID | Yes | ID of the specific batch to dispense from (FEFO — first expiry, first out). |
quantity | int | Yes | Number of units to dispense. |
dosage | String | Yes | Dosage instructions (e.g. "1 tablet twice daily after meals"). |
instructions | String | No | Additional instructions for the patient. |
Example: dispense drugs for a prescription
curl -X POST https://hospital.katixo.com/api/v1/pharmacy/dispense \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"prescriptionId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"items": [
{
"drugId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"batchId": "11111111-1111-1111-1111-111111111111",
"quantity": 10,
"dosage": "1 tablet twice daily after meals",
"instructions": "Take for 5 days. Avoid on empty stomach."
},
{
"drugId": "c3d4e5f6-a7b8-9012-cdef-234567890123",
"batchId": "22222222-2222-2222-2222-222222222222",
"quantity": 6,
"dosage": "1 tablet once daily before breakfast",
"instructions": "Take 30 minutes before food."
},
{
"drugId": "d4e5f6a7-b8c9-0123-def0-345678901234",
"batchId": "33333333-3333-3333-3333-333333333333",
"quantity": 3,
"dosage": "1 capsule daily",
"instructions": "Complete the full course of 3 days."
}
]
}'
# Response (201 Created)
{
"success": true,
"message": "Drugs dispensed successfully",
"data": {
"id": "e5f6a7b8-c9d0-1234-ef01-456789012345",
"dispenseNumber": "DIS-2026-003412",
"prescriptionId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"patientName": "Anita Kumari Verma",
"patientUhid": "UHID-2026-004580",
"status": "DISPENSED",
"dispensedAt": "2026-06-12T14:30:00Z",
"dispensedBy": "Pharmacist Ravi Shankar",
"items": [
{
"drugId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"drugName": "Paracetamol 500mg",
"batchNumber": "PCM-2026-A045",
"quantity": 10,
"unitPrice": 2.20,
"amount": 22.00,
"dosage": "1 tablet twice daily after meals",
"instructions": "Take for 5 days. Avoid on empty stomach.",
"expiryDate": "2027-11-30"
},
{
"drugId": "c3d4e5f6-a7b8-9012-cdef-234567890123",
"drugName": "Omeprazole 20mg",
"batchNumber": "OMZ-2026-B012",
"quantity": 6,
"unitPrice": 5.50,
"amount": 33.00,
"dosage": "1 tablet once daily before breakfast",
"instructions": "Take 30 minutes before food.",
"expiryDate": "2027-08-31"
},
{
"drugId": "d4e5f6a7-b8c9-0123-def0-345678901234",
"drugName": "Azithromycin 250mg",
"batchNumber": "AZT-2026-C008",
"quantity": 3,
"unitPrice": 18.00,
"amount": 54.00,
"dosage": "1 capsule daily",
"instructions": "Complete the full course of 3 days.",
"expiryDate": "2027-06-30"
}
],
"subtotal": 109.00,
"taxAmount": 13.08,
"totalAmount": 122.08,
"createdAt": "2026-06-12T14:30:00Z"
},
"errors": null
}
List dispensing records
GET/api/v1/pharmacy/dispense
Returns a paginated list of dispensing records. Use query parameters to filter by patient, date, or status.
Query parameters
| Parameter | Type | Description |
|---|
patientId | UUID | Filter by patient. |
date | LocalDate | Filter by dispensing date (YYYY-MM-DD). |
status | String | Filter by status: PENDING, DISPENSED, RETURNED. |
page | int | Page number (zero-based, default: 0). |
size | int | Results per page (default: 20). |
curl "https://hospital.katixo.com/api/v1/pharmacy/dispense?date=2026-06-12&status=DISPENSED&page=0&size=10" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
# Response
{
"success": true,
"message": "Dispensing records retrieved successfully",
"data": {
"content": [
{
"id": "e5f6a7b8-c9d0-1234-ef01-456789012345",
"dispenseNumber": "DIS-2026-003412",
"prescriptionId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"patientName": "Anita Kumari Verma",
"patientUhid": "UHID-2026-004580",
"status": "DISPENSED",
"dispensedAt": "2026-06-12T14:30:00Z",
"dispensedBy": "Pharmacist Ravi Shankar",
"totalAmount": 122.08,
"itemCount": 3,
"createdAt": "2026-06-12T14:30:00Z"
}
],
"page": 0,
"size": 10,
"totalElements": 1,
"totalPages": 1,
"last": true
},
"errors": null
}
Get dispense details
GET/api/v1/pharmacy/dispense/{dispenseId}
Retrieves the full details of a dispensing record including all items, batch information, dosage instructions, and pricing. Returns ApiResponse<DispenseResponse>.
curl https://hospital.katixo.com/api/v1/pharmacy/dispense/e5f6a7b8-c9d0-1234-ef01-456789012345 \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Return dispensed drugs
POST/api/v1/pharmacy/returns
Process a return of dispensed drugs. Stock is restored to the original batch and the dispensing record is updated. Partial returns are supported — you can return a subset of the dispensed items or a lesser quantity.
Request body
| Field | Type | Required | Description |
|---|
dispenseId | UUID | Yes | ID of the original dispensing record. |
items | ReturnItemRequest[] | Yes | Items to return. See item fields below. |
ReturnItemRequest fields
| Field | Type | Required | Description |
|---|
drugId | UUID | Yes | ID of the drug being returned. |
quantity | int | Yes | Number of units being returned (must not exceed dispensed quantity). |
reason | String | Yes | Reason for the return (e.g. "Patient discharged early", "Adverse reaction"). |
curl -X POST https://hospital.katixo.com/api/v1/pharmacy/returns \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"dispenseId": "e5f6a7b8-c9d0-1234-ef01-456789012345",
"items": [
{
"drugId": "d4e5f6a7-b8c9-0123-def0-345678901234",
"quantity": 2,
"reason": "Patient discharged early, 2 out of 3 Azithromycin capsules unused"
}
]
}'
# Response
{
"success": true,
"message": "Drug return processed successfully",
"data": {
"id": "f6a7b8c9-d0e1-2345-f012-567890123456",
"returnNumber": "RET-2026-000891",
"dispenseId": "e5f6a7b8-c9d0-1234-ef01-456789012345",
"patientName": "Anita Kumari Verma",
"patientUhid": "UHID-2026-004580",
"items": [
{
"drugId": "d4e5f6a7-b8c9-0123-def0-345678901234",
"drugName": "Azithromycin 250mg",
"quantity": 2,
"refundAmount": 36.00,
"reason": "Patient discharged early, 2 out of 3 Azithromycin capsules unused"
}
],
"totalRefundAmount": 36.00,
"processedAt": "2026-06-13T10:15:00Z",
"processedBy": "Pharmacist Ravi Shankar",
"createdAt": "2026-06-13T10:15:00Z"
},
"errors": null
}
Check drug stock
GET/api/v1/pharmacy/stock
Check real-time stock levels for a specific drug or batch. Returns available quantity, batch details, and expiry information. Uses the same inventory engine as Katasticho ERP.
Query parameters
| Parameter | Type | Description |
|---|
drugId | UUID | Filter stock by drug. Returns all batches for this drug. |
batchId | UUID | Filter stock by specific batch. Returns single batch details. |
curl "https://hospital.katixo.com/api/v1/pharmacy/stock?drugId=a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
# Response
{
"success": true,
"message": "Stock details retrieved successfully",
"data": {
"drugId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"drugName": "Paracetamol 500mg",
"totalAvailable": 2450,
"reorderLevel": 500,
"batches": [
{
"batchId": "11111111-1111-1111-1111-111111111111",
"batchNumber": "PCM-2026-A045",
"availableQuantity": 1200,
"purchasePrice": 1.80,
"sellingPrice": 2.20,
"manufacturingDate": "2026-01-15",
"expiryDate": "2027-11-30",
"receivedDate": "2026-02-10",
"supplier": "Cipla Ltd"
},
{
"batchId": "44444444-4444-4444-4444-444444444444",
"batchNumber": "PCM-2026-A052",
"availableQuantity": 1250,
"purchasePrice": 1.85,
"sellingPrice": 2.20,
"manufacturingDate": "2026-03-20",
"expiryDate": "2028-03-31",
"receivedDate": "2026-04-05",
"supplier": "Cipla Ltd"
}
]
},
"errors": null
}
Error handling
All error responses follow the standard ApiResponse wrapper with success: false and details in the errors array.
# 400 Bad Request — validation error
{
"success": false,
"message": "Validation failed",
"data": null,
"errors": [
"prescriptionId: must not be null",
"items: must not be empty"
]
}
# 409 Conflict — insufficient stock
{
"success": false,
"message": "Insufficient stock",
"data": null,
"errors": ["Paracetamol 500mg: requested 100, available 45 in batch PCM-2026-A045"]
}
# 422 Unprocessable Entity — expired batch
{
"success": false,
"message": "Cannot dispense from expired batch",
"data": null,
"errors": ["Batch OMZ-2025-B003 expired on 2026-01-31. Select a valid batch."]
}