function apiAbort(obj) { writeOutput(serializeJSON(obj)); abort; } function readJsonBody() { raw = toString(getHttpRequestData().content); if (isNull(raw) || len(trim(raw)) EQ 0) return {}; try { parsed = deserializeJSON(raw); } catch(any e) { apiAbort({ OK=false, ERROR="bad_json", MESSAGE="Invalid JSON body" }); } // We only accept object bodies if (!isStruct(parsed)) return {}; return parsed; } data = readJsonBody(); // Auth/business gating should already happen in /api/Application.cfm, // but keep this defensive so the file is safe standalone. if (!structKeyExists(request, "UserID") || !isNumeric(request.UserID) || request.UserID LTE 0) { apiAbort({ OK=false, ERROR="not_logged_in" }); } if (!structKeyExists(request, "BusinessID") || !isNumeric(request.BusinessID) || request.BusinessID LTE 0) { apiAbort({ OK=false, ERROR="no_business_selected" }); } // Default behavior: only active beacons unless onlyActive is explicitly false/0 onlyActive = true; if (structKeyExists(data, "onlyActive")) { if (isBoolean(data.onlyActive)) { onlyActive = data.onlyActive; } else if (isNumeric(data.onlyActive)) { onlyActive = (int(data.onlyActive) EQ 1); } else if (isSimpleValue(data.onlyActive)) { onlyActive = (lcase(trim(toString(data.onlyActive))) EQ "true"); } } SELECT BeaconID, BusinessID, BeaconName, UUID, NamespaceId, InstanceId, IsActive, CreatedAt, UpdatedAt FROM Beacons WHERE BusinessID = AND IsActive = 1 ORDER BY BeaconName, BeaconID #serializeJSON({ OK=true, ERROR="", BusinessID=request.BusinessID, COUNT=arrayLen(beacons), BEACONS=beacons })#