Skip to content

Inward Item Request API

Dr M H B Ariyaratne edited this page Jul 4, 2026 · 2 revisions

Inward Item Request API

Overview

The Inward Item Request API (/api/itemrequests) lets an external system — such as a patient mobile app or a ward request terminal — submit service requests (e.g. ward services, investigations) and stock item requests (e.g. medicines, consumables) against an admitted patient's BHT.

Requests are saved as Pending — the patient is not charged and no stock moves. Each request is routed to a target department's in-app queue, where a privileged department user processes each line by billing it through the normal Add Services/Investigations page (services) or Direct Issue to BHTs page (stock items), or rejects still-pending lines with a reason. Status is tracked per line, so a request can be fulfilled gradually across more than one visit, and can end up partially fulfilled and partially rejected.

Important: Processing and rejection happen only inside HMIS — there is no API for them. The external system polls GET /api/itemrequests/{id} to learn the outcome.

For the in-app side of the workflow, see Inward Service and Item Requests (Approval Queue).


Authentication

All endpoints require an API key in the Finance HTTP header:

Finance: <your-api-key>

API keys are issued in the HMIS Admin panel under API Key Management. The key must be active (not retired), activated, and not expired. Missing or invalid keys return 401.


Response Envelope

{"status": "success", "code": 200, "data": { ... }}
{"status": "error", "code": 400, "message": "..."}

Endpoints

1. Submit a Request

POST /api/itemrequests

Request body:

{
  "bhtNo": "RH/2026/001234",
  "targetDepartmentId": 42,
  "comments": "Patient requested via mobile app",
  "lines": [
    {"itemId": 1001, "qty": 1},
    {"itemId": 2002, "qty": 2}
  ]
}

A single request may mix service lines and stock item lines. Validation rules:

  • bhtNo must be an active admission (not discharged, final bill not settled)
  • targetDepartmentId must be an active department
  • At least one line; every itemId must be an active item; every qty must be greater than 0

Response 200 — the request in PENDING state:

{
  "status": "success",
  "code": 200,
  "data": {
    "id": 98765,
    "requestNo": "Inward//26/000123",
    "bhtNo": "RH/2026/001234",
    "targetDepartmentId": 42,
    "targetDepartmentName": "Ward",
    "status": "PENDING",
    "comments": "Patient requested via mobile app",
    "createdAt": "2026-07-02 09:15:00",
    "createdBy": "api-user",
    "fulfillingBillIds": [],
    "lines": [
      {"billItemId": 111, "itemId": 1001, "itemName": "Oxygen Charges", "itemType": "SERVICE", "qty": 1.0, "netValue": 0.0, "status": "PENDING"},
      {"billItemId": 112, "itemId": 2002, "itemName": "Panadol 500mg tab", "itemType": "INVENTORY", "qty": 2.0, "netValue": 0.0, "status": "PENDING"}
    ]
  }
}

2. Poll a Request's Status

GET /api/itemrequests/{id}

Returns the same structure as above. status on the request reflects the mix of its lines — PENDING, PARTIALLY_FULFILLED, FULFILLED, REJECTED, PARTIALLY_FULFILLED_AND_REJECTED, or CANCELLED. fulfillingBillIds lists every distinct real bill id that has fulfilled at least one line so far. Each line in lines carries its own status (PENDING / FULFILLED / REJECTED), and once fulfilled or rejected also carries fulfillingBillId + fulfillingBillType, or rejectionReason respectively. Unknown ids return 404.

Example of a partially processed request (one line billed, one still pending):

{
  "status": "success",
  "code": 200,
  "data": {
    "id": 98765,
    "requestNo": "Inward//26/000123",
    "status": "PARTIALLY_FULFILLED",
    "fulfillingBillIds": [55321],
    "lines": [
      {"billItemId": 111, "itemId": 1001, "itemName": "Oxygen Charges", "itemType": "SERVICE",
       "qty": 1.0, "netValue": 500.0, "status": "FULFILLED",
       "fulfillingBillId": 55321, "fulfillingBillType": "InwardBill"},
      {"billItemId": 112, "itemId": 2002, "itemName": "Panadol 500mg tab", "itemType": "INVENTORY",
       "qty": 2.0, "netValue": 0.0, "status": "PENDING"}
    ]
  }
}

3. List / Search Requests

GET /api/itemrequests?targetDepartmentId=&status=&fromDate=&toDate=&limit=

All query parameters are optional:

Parameter Format Meaning
targetDepartmentId number Only requests for this department
status PENDING | PARTIALLY_FULFILLED | FULFILLED | REJECTED | PARTIALLY_FULFILLED_AND_REJECTED | CANCELLED Filter by the request's overall derived status
fromDate / toDate yyyy-MM-dd Filter by submission date
limit number Maximum rows returned

Returns a list of lightweight rows: id, requestNo, bhtNo, targetDepartmentName, status, createdAt.

4. Cancel a Pending Request

PUT /api/itemrequests/{id}/cancel

Request body:

{"reason": "Duplicate submission"}

Withdraws the request while it is still PENDING (no line has been fulfilled or rejected yet). Returns the updated request with status: "CANCELLED". If any line has already been fulfilled or rejected, the call fails — cancel a request only before anyone has acted on it.


Status Lifecycle

Status is derived from the mix of line statuses, not stored as a single flag:

PENDING --(this API, cancel)--------------------------------> CANCELLED
PENDING --(department processes some lines)-----------------> PARTIALLY_FULFILLED
PENDING --(department processes all lines)-------------------> FULFILLED
PENDING --(department rejects all remaining lines)-----------> REJECTED
PARTIALLY_FULFILLED --(department rejects the rest)----------> PARTIALLY_FULFILLED_AND_REJECTED
  • PENDING — no line has been fulfilled or rejected yet.
  • PARTIALLY_FULFILLED — at least one line fulfilled, at least one still pending.
  • FULFILLED — every line fulfilled (no pending or rejected lines remain).
  • REJECTED — every line rejected, none fulfilled.
  • PARTIALLY_FULFILLED_AND_REJECTED — every line is either fulfilled or rejected, with at least one of each, and none still pending.
  • CANCELLED — withdrawn by the requesting system before any line was acted on; no charge, no stock change.

A line becomes FULFILLED the moment a department user bills or issues it through the normal Add Services / Direct Issue pages — the BHT is charged (and, for stock items, department stock deducted from the earliest-expiry non-expired batch at the batch's retail sale rate) at that point, not before. A line becomes REJECTED when a department user rejects the request's remaining lines with a reason. Fulfillment and rejection happen per line, so a single request commonly ends up PARTIALLY_FULFILLED for a while before becoming fully resolved.


Error Codes

Code Meaning
400 Validation error — unknown/retired item, quantity ≤ 0, invalid/discharged/settled BHT, unknown department, malformed JSON
401 Missing or invalid Finance API key
404 Unknown request id
409 Cancelling a request that already has a fulfilled or rejected line, or was already cancelled
500 Unexpected server error

Error responses carry a human-readable message explaining what to fix.


Setup Prerequisites

Before integrating, the hospital must configure the requestable items:

  1. Service and investigation items — created as inward services or investigations with fees and a category configured, so department staff can bill them via Add Services & Investigations.
  2. Stock items — created as stock-tracked items and stocked into each target department through the normal GRN flow. Processing an inventory line deducts that department's stock and charges the batch retail sale rate.
  3. Privileges — department users who will process/reject lines need the Inward Service/Item Request Approval / Rejection privileges.
  4. API key — issued to the integrating system via Admin → API Key Management.

The external system needs the HMIS item ids and department ids to build requests; the hospital administrator supplies these after creating the master data.


Related Pages

Clone this wiki locally