{"info":{"_postman_id":"de6ac338-9d1c-4f67-a0ca-dba6d4ef1ffa","name":"UNAI API V1.1","description":"<html><head></head><body><h1 id=\"unai-api-v11\">UNAI API V1.1</h1>\n<p>Current Postman collection for authentication, master data, device data, staff administration, socket topics, gateway status, and location-history operations. Use <code>https://rtls.lailab.online</code> as the server base URL. Except for <code>/auth/gen_token</code>, requests that access protected resources require a valid bearer token and the permission stated in each request description.</p>\n</body></html>","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","toc":[{"content":"UNAI API V1.1","slug":"unai-api-v11"}],"owner":"586765","collectionId":"de6ac338-9d1c-4f67-a0ca-dba6d4ef1ffa","publishedId":"2sBYAvuVBp","public":true,"customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"},"publishDate":"2026-09-02T07:38:30.000Z"},"item":[{"name":"authenticate","item":[{"name":"gen new token with username/password","event":[{"listen":"test","script":{"type":"text/javascript","exec":["const jsonData = pm.response.json();","if (jsonData && jsonData.access_token) {","    pm.environment.set(\"API_ACCESS_TOKEN\", jsonData.access_token);","    pm.collectionVariables.set(\"API_ACCESS_TOKEN\", jsonData.access_token);","    console.log(\"API_ACCESS_TOKEN saved\");","}","if (jsonData && jsonData.socket_token) {","    pm.environment.set(\"API_SOCKET_TOKEN\", jsonData.socket_token);","    pm.collectionVariables.set(\"API_SOCKET_TOKEN\", jsonData.socket_token);","    console.log(\"API_SOCKET_TOKEN saved\");","}","if (jsonData && jsonData.refresh_token) {","    pm.environment.set(\"REFRESH_TOKEN\", jsonData.refresh_token);","    pm.collectionVariables.set(\"REFRESH_TOKEN\", jsonData.refresh_token);","    console.log(\"REFRESH_TOKEN saved\");","}","","// Save Socket.IO Message Guide variables.","if (jsonData && jsonData.socket_token) {","    pm.environment.set(\"socket_token\", jsonData.socket_token);","    pm.collectionVariables.set(\"socket_token\", jsonData.socket_token);","}"],"id":"32776d8c-cf1f-492c-b897-f5666996697b"}}],"id":"a4235aff-dab2-4ce1-898b-76e57b8b25d4","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"username","value":"{{USERNAME}}","description":"<p>USERNAME</p>\n","type":"text"},{"key":"password","value":"{{PASSWORD}}","description":"<p>PASSWORD</p>\n","type":"text"},{"key":"token_expire_time_in_minute","value":"60","type":"text","disabled":true},{"key":"refresh_token_expire_time_in_minute","value":"60","type":"text","disabled":true},{"key":"socket_token_type","value":"rs256","type":"text","uuid":"0ae14fcf-d14b-4f2f-bfef-9d763d819cb7"},{"key":"client_app","value":"drtls_manager","description":"<p>Optional. Use drtls_manager to restrict login to SuperAdmin/SI.</p>\n","type":"text","disabled":true}]},"url":"https://rtls.lailab.online/auth/gen_token","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Authenticates a staff account with <code>username</code> and <code>password</code>, then returns a signed access token, refresh token, socket token, session and staff metadata, and the resolved access scope. Optional expiry fields are bounded by the server configuration.</p>\n<h3 id=\"authentication\">Authentication</h3>\n<p>No bearer token is required. <code>username</code> and <code>password</code> are required.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>The collection provides these fields: <code>username</code>, <code>password</code>, <code>token_expire_time_in_minute</code>, <code>refresh_token_expire_time_in_minute</code>, <code>socket_token_type</code>, <code>client_app</code>. Fields marked disabled in Postman are optional examples unless the purpose section states otherwise.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["auth","gen_token"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"a4235aff-dab2-4ce1-898b-76e57b8b25d4"},{"name":"gen new token with refreshtoken","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"66710ee0-6377-4c24-a2fd-bf4f6f62e00f"}}],"id":"7ddc19a7-0be5-4858-8cc1-03f7adde826a","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"url":"https://rtls.lailab.online/auth/refresh_token","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Rotates a valid bearer refresh token and returns a new token pair for the same active session. The supplied refresh token must be valid and must match an active or supported legacy session.</p>\n<h3 id=\"authentication\">Authentication</h3>\n<p>Send the refresh token as a bearer token.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["auth","refresh_token"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"7ddc19a7-0be5-4858-8cc1-03f7adde826a"}],"id":"f4eb273a-7077-461a-ac71-65f331d6c401","description":"<p>Issues and rotates access and refresh tokens for API authentication.</p>\n","_postman_id":"f4eb273a-7077-461a-ac71-65f331d6c401"},{"name":"place","item":[{"name":"get all place","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"3058d954-429c-4c16-a4ae-0e0c7eac9a41"}}],"id":"afdceef8-4404-4a4e-8509-c61fb91e6c8f","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_all_place","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns all place within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_all_place"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"afdceef8-4404-4a4e-8509-c61fb91e6c8f"},{"name":"get place by id","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"1ae49eed-caab-4cf2-8069-56c426c802af"}}],"id":"2f5bf417-4691-4d6f-889f-3b6cb3ca4abd","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_place_by_id/[place_id]","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns place by id within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>place_id</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_place_by_id","[place_id]"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"2f5bf417-4691-4d6f-889f-3b6cb3ca4abd"},{"name":"get place device access","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"019d61df-6fcb-4cad-b20e-51c45c7bc1cb"}}],"id":"29e33693-dd02-467f-a217-e361b57ca85c","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/place_device_access","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns place device access within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_place_device_access</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","place_device_access"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"29e33693-dd02-467f-a217-e361b57ca85c"},{"name":"get place device access by id","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"b736f006-b452-4ead-9828-54210023f15f"}}],"id":"5779e716-6cf1-4153-82f6-b6c27ff68f32","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/place_device_access/[place_id]","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns place device access by id within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_place_device_access</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>place_id</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","place_device_access","[place_id]"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"5779e716-6cf1-4153-82f6-b6c27ff68f32"}],"id":"ba82f827-bf54-46ca-850e-8bb642791d64","description":"<p>Reads places and place-level device-access assignments visible to the authenticated staff account.</p>\n","_postman_id":"ba82f827-bf54-46ca-850e-8bb642791d64"},{"name":"building","item":[{"name":"get all building by staff","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"9837e35c-1f99-465b-ac28-2ede4fce5ed7"}}],"id":"ca50084c-b7e3-4b17-b820-efc0d4fe09a9","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_all_building","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns all building by staff within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_all_building"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"ca50084c-b7e3-4b17-b820-efc0d4fe09a9"},{"name":"get building by place id","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"a99b70d4-e0af-4795-9811-f429cfcd300c"}}],"id":"077446c6-5e45-4bf9-bd9b-1034ff09060e","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_building_by_place_id/[PLACE_ID]","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns building by place id within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>PLACE_ID</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_building_by_place_id","[PLACE_ID]"],"host":["https://rtls.lailab.online"],"query":[{"disabled":true,"key":null,"value":""}],"variable":[]}},"response":[],"_postman_id":"077446c6-5e45-4bf9-bd9b-1034ff09060e"},{"name":"get building by id","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"a83457a0-a1e6-4398-906d-67db2767ec0a"}}],"id":"8f2be72b-3b4e-4fe4-b84a-6e852b3bf970","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_building_by_id/[BUILDING_ID]","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns building by id within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>BUILDING_ID</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_building_by_id","[BUILDING_ID]"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"8f2be72b-3b4e-4fe4-b84a-6e852b3bf970"}],"id":"5f917420-5414-431e-b284-381582a92812","description":"<p>Reads buildings visible to the authenticated staff account, optionally scoped by place or building ID.</p>\n","_postman_id":"5f917420-5414-431e-b284-381582a92812"},{"name":"floor","item":[{"name":"get all floor","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"465e970b-4e4b-4e30-ab81-b96d4725da4f"}}],"id":"5fd97eb2-3713-4942-98ea-1f58a087f512","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_all_floor","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns all floor within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_all_floor"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"5fd97eb2-3713-4942-98ea-1f58a087f512"},{"name":"get floor by id","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"e13e706b-c3a4-44cc-8767-92b2d6a43a94"}}],"id":"52445fd2-eb9f-4603-8a44-efb18b613613","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_floor_by_id/[FLOOR_ID]","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns floor by id within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>FLOOR_ID</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_floor_by_id","[FLOOR_ID]"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"52445fd2-eb9f-4603-8a44-efb18b613613"},{"name":"get floor by building id","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"663a691a-6d40-4632-baa4-78e75f4fdb50"}}],"id":"52375aa3-2a1b-4c84-a270-349d6f04d7eb","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_floors_by_building_id/[BUILDING_ID]","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns floor by building id within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>BUILDING_ID</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_floors_by_building_id","[BUILDING_ID]"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"52375aa3-2a1b-4c84-a270-349d6f04d7eb"}],"id":"40030c93-76df-4c0f-a84d-5dc5584a0d45","description":"<p>Reads floors visible to the authenticated staff account, optionally scoped by building or floor ID.</p>\n","_postman_id":"40030c93-76df-4c0f-a84d-5dc5584a0d45"},{"name":"zone","item":[{"name":"get all zone","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"40196a9d-08f6-48a4-9c06-e2d9f188318f"}}],"id":"524a7962-2e09-4f06-9986-585a4e98bfa0","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_all_zone","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns every zone visible to the authenticated staff account, including floor, building, and place metadata. SuperAdmin receives all zones; other roles receive zones only from assigned buildings.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns a JSON array. Invalid or expired authentication, insufficient permission, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_all_zone"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"524a7962-2e09-4f06-9986-585a4e98bfa0"},{"name":"get zone by floor id","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"91aef035-046d-42e0-aba9-20cadc041e58"}}],"id":"3884822a-f5a0-4257-bdaf-8a1b15e8ca7d","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_zone_by_floor_id/[FLOOR_ID]","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns zone by floor id within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>FLOOR_ID</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_zone_by_floor_id","[FLOOR_ID]"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"3884822a-f5a0-4257-bdaf-8a1b15e8ca7d"},{"name":"get shelf zone","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"5ff0e1c3-8bc1-4972-92f1-cb5aefd74a23"}}],"id":"966c6c28-83dd-473b-8667-320edca3cd95","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_shelf_zone","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns shelf zone within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_shelf_zone"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"966c6c28-83dd-473b-8667-320edca3cd95"},{"name":"get zone by id","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"1be3b435-35aa-46bf-a163-c061d9c2eb1c"}}],"id":"d3b2589e-d706-4786-8bcd-86dedfae6ba1","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_zone_by_zone_id/[ZONE_ID]","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns zone by id within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>ZONE_ID</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_zone_by_zone_id","[ZONE_ID]"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"d3b2589e-d706-4786-8bcd-86dedfae6ba1"}],"id":"afe3c744-5f7e-4d01-b5d5-9d4dfaa8ab0d","description":"<p>Reads floor zones and shelf-zone metadata within the authenticated staff access scope.</p>\n","_postman_id":"afe3c744-5f7e-4d01-b5d5-9d4dfaa8ab0d"},{"name":"anchor","item":[{"name":"get anchor by floor id","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"12e43901-be90-456b-b0d9-2df0a289e55d"}}],"id":"43379ddf-7082-4f41-b205-48325da9ece5","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_anchor_by_floor_id/[FLOOR_ID]","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns anchor by floor id within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>FLOOR_ID</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_anchor_by_floor_id","[FLOOR_ID]"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"43379ddf-7082-4f41-b205-48325da9ece5"},{"name":"get all anchor","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"68cabf86-5b4b-45ec-abec-8160b0db85fb"}}],"id":"86d0f610-a762-4f8a-8fbd-3fd140fa0ecf","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_all_anchor","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns all anchor within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_all_anchor"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"86d0f610-a762-4f8a-8fbd-3fd140fa0ecf"},{"name":"get anchor by id","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"23fa0377-c40b-44b6-9c79-eceadde0903b"}}],"id":"ef5b7f42-22aa-4f57-9d02-04350e8f48ff","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_anchor_by_id/[ANCHOR_ID]","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns anchor by id within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>ANCHOR_ID</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_anchor_by_id","[ANCHOR_ID]"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"ef5b7f42-22aa-4f57-9d02-04350e8f48ff"}],"id":"507a0ea1-66c6-4db6-8bc7-73dd179aa998","description":"<p>Reads anchor metadata within the authenticated staff access scope.</p>\n","_postman_id":"507a0ea1-66c6-4db6-8bc7-73dd179aa998"},{"name":"tag","item":[{"name":"get all tag","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"ff6be145-5add-42aa-a66a-d80fb2b21600"}}],"id":"03893ad6-1b58-428b-9c83-508fb19a7eab","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_all_tag","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns all tag within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_all_tag"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"03893ad6-1b58-428b-9c83-508fb19a7eab"},{"name":"get tag and sensor","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"d5b95f10-65bb-4100-acc1-aca4a6083dbe"}}],"id":"42746dbf-9f3f-421f-8236-1e1bdbeee6c5","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_tag_and_sensor","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns tag and sensor within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_tag_and_sensor"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"42746dbf-9f3f-421f-8236-1e1bdbeee6c5"},{"name":"get tag by id","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"017b92f8-fd30-4a7c-bbf2-e01e1e9f372b"}}],"id":"73b0e783-1094-470e-a484-fa455fe5726c","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_tag_by_id/[TAG_ID]","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns tag by id within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>TAG_ID</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_tag_by_id","[TAG_ID]"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"73b0e783-1094-470e-a484-fa455fe5726c"},{"name":"upsert tag by id","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"d88cbaa9-13cf-4d53-8811-65bd943dd24a"}}],"id":"7643051d-bcd5-4807-aa73-2dae9d110e47","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"id","value":"5449","description":"<p>Required positive database ID used to create or update the tag.</p>\n","type":"text"},{"key":"tag_id","value":"b9407f30-f5f8-466e-aff9-25556b57fe6d_10_1","description":"<p>Beacon or hardware tag identifier stored on the tag record.</p>\n","type":"text"},{"key":"label","value":"VSTR-NT-001","description":"<p>Human-readable name or label for the tag.</p>\n","type":"text"},{"key":"ui_display","value":"V001","description":"<p>Short display name shown in the user interface.</p>\n","type":"text"},{"key":"major","value":"10","description":"<p>Beacon major value used with the UUID and minor value.</p>\n","type":"text"},{"key":"minor","value":"1","description":"<p>Required when creating a new tag; optional when updating.</p>\n","type":"text"},{"key":"uuid","value":"b9407f30-f5f8-466e-aff9-25556b57fe6d","description":"<p>Beacon UUID used with the major and minor values.</p>\n","type":"text"},{"key":"manufacturer","value":"","description":"<p>Tag hardware manufacturer name.</p>\n","type":"text","disabled":true},{"key":"volt_battery","value":"","description":"<p>Battery voltage reported by the tag.</p>\n","type":"text","disabled":true},{"key":"firmware_version","value":"","description":"<p>Firmware version reported by the tag.</p>\n","type":"text","disabled":true},{"key":"mac_address","value":"","description":"<p>MAC address of the tag hardware.</p>\n","type":"text","disabled":true},{"key":"blink_period","value":"","description":"<p>Beacon blink or advertising period.</p>\n","type":"text","disabled":true},{"key":"tx_ant_delay","value":"","description":"<p>Transmit antenna delay calibration value.</p>\n","type":"text","disabled":true},{"key":"rx_ant_delay","value":"","description":"<p>Receive antenna delay calibration value.</p>\n","type":"text","disabled":true},{"key":"device_type_id","value":"1","description":"<p>Database ID of the tag device type.</p>\n","type":"text"},{"key":"x","value":"","description":"<p>Tag X coordinate in the configured place or map.</p>\n","type":"text","disabled":true},{"key":"y","value":"","description":"<p>Tag Y coordinate in the configured place or map.</p>\n","type":"text","disabled":true},{"key":"z","value":"","description":"<p>Tag Z coordinate or height in the configured place or map.</p>\n","type":"text","disabled":true},{"key":"place_id","value":"1","description":"<p>Non-SuperAdmin callers must have access to this place.</p>\n","type":"text"},{"key":"tagcol","value":"","description":"<p>Optional application-specific tag classification value.</p>\n","type":"text","disabled":true},{"key":"device_id_thingsboard","value":"","description":"<p>ThingsBoard device identifier associated with the tag.</p>\n","type":"text","disabled":true},{"key":"device_access_token_thingsboard","value":"","description":"<p>ThingsBoard access token for the associated device.</p>\n","type":"text","disabled":true},{"key":"disable","value":"","description":"<p>Disable flag for the tag; use 0 for enabled and 1 for disabled.</p>\n","type":"text","disabled":true},{"key":"path_id","value":"","description":"<p>Database ID of the path used for tag snapping.</p>\n","type":"text","disabled":true},{"key":"status","value":"","description":"<p>Current active status of the tag.</p>\n","type":"text","disabled":true},{"key":"method_id","value":"","description":"<p>Database ID of the positioning method assigned to the tag.</p>\n","type":"text","disabled":true},{"key":"serial_number","value":"","description":"<p>Serial number printed on or reported by the tag hardware.</p>\n","type":"text","disabled":true},{"key":"paired_with_id","value":"","description":"<p>Identifier of a tag paired with this tag, when applicable.</p>\n","type":"text","disabled":true},{"key":"batt_percentage","value":"","description":"<p>Battery percentage reported by the tag.</p>\n","type":"text","disabled":true},{"key":"batt_change_date","value":"","description":"<p>Date and time when the battery value last changed.</p>\n","type":"text","disabled":true},{"key":"link_with_gateway_id","value":"","description":"<p>Database ID of the gateway linked to this tag.</p>\n","type":"text","disabled":true}]},"url":"https://rtls.lailab.online/api/v1/upsert_tag_by_id","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Creates a tag with the supplied positive integer <code>id</code> when it does not exist, or updates the whitelisted fields of the existing tag with that ID. A create returns HTTP 201 with <code>action: created</code>; an update returns HTTP 200 with <code>action: updated</code>.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_manage_device_data</code>. Updating an existing tag also requires access to that tag unless the caller is SuperAdmin. Supplying <code>place_id</code> requires access to that place for non-SuperAdmin callers.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>Submit the body as <code>application/x-www-form-urlencoded</code>, consistent with the other Tag APIs. <code>id</code> is always required and must be a positive integer. <code>minor</code> is required when creating a new tag. Supported optional fields are <code>tag_id</code>, <code>label</code>, <code>ui_display</code>, <code>major</code>, <code>minor</code>, <code>uuid</code>, <code>manufacturer</code>, <code>volt_battery</code>, <code>firmware_version</code>, <code>mac_address</code>, <code>blink_period</code>, <code>tx_ant_delay</code>, <code>rx_ant_delay</code>, <code>device_type_id</code>, <code>x</code>, <code>y</code>, <code>z</code>, <code>place_id</code>, <code>tagcol</code>, <code>device_id_thingsboard</code>, <code>device_access_token_thingsboard</code>, <code>disable</code>, <code>path_id</code>, <code>status</code>, <code>method_id</code>, <code>serial_number</code>, <code>paired_with_id</code>, <code>batt_percentage</code>, <code>batt_change_date</code>, and <code>link_with_gateway_id</code>. Omitted fields are preserved during update.</p>\n<p><code>visitor_id</code>, <code>created_by</code>, <code>updated_by</code>, <code>created_at</code>, and <code>updated_at</code> are server-managed or ignored. Assign a visitor through <code>user.tag_id</code>.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns <code>{ message, action, data }</code> on success. HTTP 400 indicates an invalid ID or a missing <code>minor</code> during creation; 401/403 indicates an authentication, API-permission, tag-scope, or place-scope failure; 409 indicates an ID conflict.</p>\n","urlObject":{"path":["api","v1","upsert_tag_by_id"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"7643051d-bcd5-4807-aa73-2dae9d110e47"},{"name":"insert tag","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"19d90230-92d1-4fbd-b15f-ca85e9b96e4d"}}],"id":"ca9d6a6f-253c-4eb1-9ff5-33aec7b2993c","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"tag_id","value":"","type":"text","disabled":true},{"key":"label","value":"","type":"text","disabled":true},{"key":"ui_display","value":"","type":"text","disabled":true},{"key":"major","value":"","type":"text","disabled":true},{"key":"minor","value":"","type":"text","disabled":true},{"key":"uuid","value":"","type":"text","disabled":true},{"key":"manufacturer","value":"","type":"text","disabled":true},{"key":"volt_battery","value":"","type":"text","disabled":true},{"key":"firmware_version","value":"","type":"text","disabled":true},{"key":"mac_address","value":"","type":"text","disabled":true},{"key":"blink_period","value":"","type":"text","disabled":true},{"key":"tx_ant_delay","value":"","type":"text","disabled":true},{"key":"rx_ant_delay","value":"","type":"text","disabled":true},{"key":"date_time","value":"","type":"text","disabled":true},{"key":"device_type_id","value":"","type":"text","disabled":true},{"key":"x","value":"","type":"text","disabled":true},{"key":"y","value":"","type":"text","disabled":true},{"key":"z","value":"","type":"text","disabled":true},{"key":"tagcol","value":"","type":"text","disabled":true},{"key":"device_id_thingsboard","value":"","type":"text","disabled":true},{"key":"device_access_token_thingsboard","value":"","type":"text","disabled":true},{"key":"disable","value":"","type":"text","disabled":true},{"key":"path_id","value":"","type":"text","disabled":true},{"key":"visitor_id","value":"","type":"text","disabled":true},{"key":"status","value":"","type":"text","disabled":true},{"key":"created_by","value":"","type":"text","disabled":true},{"key":"updated_by","value":"","type":"text","disabled":true},{"key":"created_at","value":"","type":"text","disabled":true},{"key":"updated_at","value":"","type":"text","disabled":true},{"key":"method_id","value":"","type":"text","disabled":true},{"key":"serial_number","value":"","type":"text","disabled":true},{"key":"paired_with_id","value":"","type":"text","disabled":true}]},"url":"https://rtls.lailab.online/api/v1/insert_tag","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Creates a tag record from the supplied tag/device fields within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_manage_device_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>The collection provides these fields: <code>tag_id</code>, <code>label</code>, <code>ui_display</code>, <code>major</code>, <code>minor</code>, <code>uuid</code>, <code>manufacturer</code>, <code>volt_battery</code>, <code>firmware_version</code>, <code>mac_address</code>, <code>blink_period</code>, <code>tx_ant_delay</code>, <code>rx_ant_delay</code>, <code>date_time</code>, <code>device_type_id</code>, <code>x</code>, <code>y</code>, <code>z</code>, <code>tagcol</code>, <code>device_id_thingsboard</code>, <code>device_access_token_thingsboard</code>, <code>disable</code>, <code>path_id</code>, <code>visitor_id</code>, <code>status</code>, <code>created_by</code>, <code>updated_by</code>, <code>created_at</code>, <code>updated_at</code>, <code>method_id</code>, <code>serial_number</code>, <code>paired_with_id</code>. Fields marked disabled in Postman are optional examples unless the purpose section states otherwise.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","insert_tag"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"ca9d6a6f-253c-4eb1-9ff5-33aec7b2993c"},{"name":"get_tag_and_sensor","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"4d09856a-9c96-49e7-9ccf-3a6dfc3cfcec"}}],"id":"5f657564-f139-4bd3-b536-07d6fc09f25c","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_sensor_and_tag_data","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns tag and sensor within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_sensor_and_tag_data"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"5f657564-f139-4bd3-b536-07d6fc09f25c"}],"id":"86a5a0a7-a2f0-4332-8e22-3491eab56a0e","description":"<p>Reads tag and sensor metadata and creates tags within the authenticated staff access scope.</p>\n","_postman_id":"86a5a0a7-a2f0-4332-8e22-3491eab56a0e"},{"name":"user","item":[{"name":"get all user","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"f6b41278-d4c2-490c-8caf-e93d9adb72d7"}}],"id":"7c823c1d-95f6-4f20-aa9c-f4bbdf6ec74f","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_all_user","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns all user within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_all_user"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"7c823c1d-95f6-4f20-aa9c-f4bbdf6ec74f"},{"name":"get user by id","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"3f289648-11a5-42ad-acc9-dbe593e9ec11"}}],"id":"4e6bc60d-2047-447b-a350-001db76708e6","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_user_by_id/[USER_ID]","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns user by id within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>USER_ID</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_user_by_id","[USER_ID]"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"4e6bc60d-2047-447b-a350-001db76708e6"},{"name":"update user info","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"968498c7-dbcf-4da6-a87a-0d6d3e1a6078"}}],"id":"8b87729c-54cf-412d-b83e-64b8b5d8be41","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"PATCH","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"first_name","value":"","type":"text"},{"key":"last_name","value":"","type":"text"},{"key":"image","value":"","type":"text"},{"key":"nick_name","value":"","type":"text","disabled":true},{"key":"gender","value":"","type":"text","disabled":true},{"key":"email","value":"","type":"text","disabled":true},{"key":"birthday","value":"","type":"text","disabled":true},{"key":"tag_id","value":"","type":"text","disabled":true},{"key":"init_floor","value":"","type":"text","disabled":true},{"key":"last_floor","value":"","type":"text","disabled":true},{"key":"group_user","value":"","type":"text","disabled":true},{"key":"status","value":"","type":"text","disabled":true},{"key":"alt_status","value":"","type":"text","disabled":true},{"key":"avatar","value":"","type":"text","disabled":true},{"key":"notification_level","value":"","type":"text","disabled":true},{"key":"created_by","value":"","type":"text","disabled":true},{"key":"updated_by","value":"","type":"text","disabled":true},{"key":"already_registered_nt_racing","value":"","type":"text","disabled":true},{"key":"nstda_id","value":"","type":"text","disabled":true},{"key":"action_status","value":"","type":"text","disabled":true}]},"url":"https://rtls.lailab.online/api/v1/update_user_info/[USER_ID]","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Updates only the supplied fields of the user identified by <code>USER_ID</code>. The user must be accessible to the authenticated staff account; update audit data is applied by the server.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_manage_device_data</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>USER_ID</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>The collection provides these fields: <code>first_name</code>, <code>last_name</code>, <code>image</code>, <code>nick_name</code>, <code>gender</code>, <code>email</code>, <code>birthday</code>, <code>tag_id</code>, <code>init_floor</code>, <code>last_floor</code>, <code>group_user</code>, <code>status</code>, <code>alt_status</code>, <code>avatar</code>, <code>notification_level</code>, <code>created_by</code>, <code>updated_by</code>, <code>already_registered_nt_racing</code>, <code>nstda_id</code>, <code>action_status</code>. Fields marked disabled in Postman are optional examples unless the purpose section states otherwise.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","update_user_info","[USER_ID]"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"8b87729c-54cf-412d-b83e-64b8b5d8be41"},{"name":"Insert user","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"070282d0-c5ca-497d-b6a2-3facccec65d5"}}],"id":"6d2c7e33-bec3-4d2f-897a-141710ee0bcf","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"first_name","value":"","type":"text","disabled":true},{"key":"last_name","value":"","type":"text","disabled":true},{"key":"nick_name","value":"","type":"text","disabled":true},{"key":"gender","value":"","type":"text","disabled":true},{"key":"email","value":"","type":"text","disabled":true},{"key":"birthday","value":"","type":"text","disabled":true},{"key":"tag_id","value":"","type":"text","disabled":true},{"key":"init_floor","value":"","type":"text","disabled":true},{"key":"last_floor","value":"","type":"text","disabled":true},{"key":"group_user","value":"","type":"text","disabled":true},{"key":"status","value":"","type":"text","disabled":true},{"key":"alt_status","value":"","type":"text","disabled":true},{"key":"avatar","value":"","type":"text","disabled":true},{"key":"notification_level","value":"","type":"text","disabled":true},{"key":"image","value":"","type":"text","disabled":true},{"key":"created_by","value":"","type":"text","disabled":true},{"key":"updated_by","value":"","type":"text","disabled":true},{"key":"created_at","value":"","type":"text","disabled":true},{"key":"updated_at","value":"","type":"text","disabled":true},{"key":"snap_to_line_enable","value":"","type":"text","disabled":true}]},"url":"https://rtls.lailab.online/api/v1/insert_user","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Creates a tracked-user profile. <code>tag_id</code> is required and must not already be assigned to another user; omitted audit IDs and timestamps are populated by the server.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_manage_device_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>The collection provides these fields: <code>first_name</code>, <code>last_name</code>, <code>nick_name</code>, <code>gender</code>, <code>email</code>, <code>birthday</code>, <code>tag_id</code>, <code>init_floor</code>, <code>last_floor</code>, <code>group_user</code>, <code>status</code>, <code>alt_status</code>, <code>avatar</code>, <code>notification_level</code>, <code>image</code>, <code>created_by</code>, <code>updated_by</code>, <code>created_at</code>, <code>updated_at</code>, <code>snap_to_line_enable</code>. Fields marked disabled in Postman are optional examples unless the purpose section states otherwise.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","insert_user"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"6d2c7e33-bec3-4d2f-897a-141710ee0bcf"}],"id":"ade32182-9bc3-481c-83f1-1a00dd73fd70","description":"<p>Reads and manages tracked-user profiles within the authenticated staff access scope.</p>\n","_postman_id":"ade32182-9bc3-481c-83f1-1a00dd73fd70"},{"name":"gateway","item":[{"name":"get gateway runtime status","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"05efa86c-5b55-4c7b-9c07-258e5ff4716c"}}],"id":"fca7a340-e40b-4463-aa73-d83d62534574","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_gateway_runtime_status","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns the latest runtime/connectivity status for gateways visible to the authenticated staff account.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_gateway_runtime_status</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_gateway_runtime_status"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"fca7a340-e40b-4463-aa73-d83d62534574"}],"id":"3cf670a2-a301-47e0-bb4d-12ba0001c59a","description":"<p>Reads the current runtime status of gateways visible to the authenticated staff account.</p>\n","_postman_id":"3cf670a2-a301-47e0-bb4d-12ba0001c59a"},{"name":"group user","item":[{"name":"get all group user","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"9ec03cd6-6a1f-4f65-8f54-331037c80544"}}],"id":"c70a5669-28bf-4f70-bb5f-4aa805e5d65f","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_group_user","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns all group user within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_master_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_group_user"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"c70a5669-28bf-4f70-bb5f-4aa805e5d65f"}],"id":"39aabf5b-8140-4641-82f6-0ed05bdef221","description":"<p>Reads the user groups available within the authenticated staff access scope.</p>\n","_postman_id":"39aabf5b-8140-4641-82f6-0ed05bdef221"},{"name":"staff","item":[{"name":"get staff roles","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"ca8bc970-624a-4b10-96c6-59e3e753ce2b"}}],"id":"967b8b57-679b-429a-b647-7b1f1bc30c6b","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_staff_roles","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns staff roles within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_staff_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_staff_roles"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"967b8b57-679b-429a-b647-7b1f1bc30c6b"},{"name":"get all staff","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"8af64e8b-8a23-48b7-ac95-5303196ea856"}}],"id":"53933294-b992-4247-8bc8-cfb46ca98ca3","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_all_staff","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns all staff within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_staff_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_all_staff"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"53933294-b992-4247-8bc8-cfb46ca98ca3"},{"name":"get staff by id","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"854ef667-8c36-4737-a443-2d922e55b132"}}],"id":"31fd218c-92a0-4f67-a544-eb4b58f742e3","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"GET","header":[],"url":"https://rtls.lailab.online/api/v1/get_staff_by_id/1","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns staff by id within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_staff_data</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>STAFF_ID</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_staff_by_id","1"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"31fd218c-92a0-4f67-a544-eb4b58f742e3"},{"name":"insert staff","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"bfbb0ff7-a842-40d8-8843-ba79c8e5df56"}}],"id":"39a9ea81-97fa-4cdb-9122-795fcc1486f7","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"raw","raw":"{\n  \"username\": \"new_staff\",\n  \"password\": \"password123\",\n  \"first_name\": \"First\",\n  \"last_name\": \"Last\",\n  \"email\": \"staff@example.com\",\n  \"line_notify_token\": \"\",\n  \"notification_status\": 1,\n  \"staff_role_id\": 1,\n  \"is_able_to_design_floor\": 0,\n  \"building_ids\": [\n    1\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://rtls.lailab.online/api/v1/insert_staff","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Creates a staff account using the supplied identity, role, credential, and access-scope fields.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_manage_staff_data</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>The collection provides these fields: <code>username</code>, <code>password</code>, <code>first_name</code>, <code>last_name</code>, <code>email</code>, <code>line_notify_token</code>, <code>notification_status</code>, <code>staff_role_id</code>, <code>is_able_to_design_floor</code>, <code>building_ids</code>. Fields marked disabled in Postman are optional examples unless the purpose section states otherwise.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","insert_staff"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"39a9ea81-97fa-4cdb-9122-795fcc1486f7"},{"name":"update staff","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"9e54ced6-195b-4b70-918f-c9024a3cfe51"}}],"id":"caa9f406-3b6c-4368-b119-3db10d03a161","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"PATCH","header":[],"body":{"mode":"raw","raw":"{\n  \"username\": \"updated_staff\",\n  \"first_name\": \"First\",\n  \"last_name\": \"Last\",\n  \"email\": \"staff@example.com\",\n  \"line_notify_token\": \"\",\n  \"notification_status\": 1,\n  \"staff_role_id\": 1,\n  \"is_able_to_design_floor\": 0,\n  \"building_ids\": [\n    1\n  ]\n}","options":{"raw":{"language":"json"}}},"url":"https://rtls.lailab.online/api/v1/update_staff/1","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Updates the supplied fields of the staff account identified by <code>STAFF_ID</code>.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_manage_staff_data</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>STAFF_ID</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>The collection provides these fields: <code>username</code>, <code>first_name</code>, <code>last_name</code>, <code>email</code>, <code>line_notify_token</code>, <code>notification_status</code>, <code>staff_role_id</code>, <code>is_able_to_design_floor</code>, <code>building_ids</code>. Fields marked disabled in Postman are optional examples unless the purpose section states otherwise.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","update_staff","1"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"caa9f406-3b6c-4368-b119-3db10d03a161"},{"name":"remove staff","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"eefc42e2-5e9c-47aa-94a5-59a3983b4b42"}}],"id":"f3e7d184-623f-4bcf-9467-9f8bbebce745","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"DELETE","header":[],"url":"https://rtls.lailab.online/api/v1/remove_staff/1","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Removes or deactivates the staff account identified by <code>STAFF_ID</code> according to the current staff-management policy.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_manage_staff_data</code>.</p>\n<h3 id=\"path-parameters\">Path parameters</h3>\n<ul>\n<li><code>STAFF_ID</code>: Required resource identifier.</li>\n</ul>\n<h3 id=\"request-body\">Request body</h3>\n<p>No request body is required.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","remove_staff","1"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"f3e7d184-623f-4bcf-9467-9f8bbebce745"}],"id":"be6d2fe6-8d75-4598-83f7-dc4136bbc366","description":"<p>Reads and manages staff accounts and staff roles. Management operations require staff-management permission.</p>\n","_postman_id":"be6d2fe6-8d75-4598-83f7-dc4136bbc366"},{"name":"location history","item":[{"name":"last location by floor","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"ee9fb78a-cd8d-47d8-b4ef-173fe9c98fdb"}}],"id":"8faee0a1-3cb0-4aed-b7d6-24185aee1636","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"floor_id","value":"[floor_id]","description":"<p>[floor_id]</p>\n","type":"text"}]},"url":"https://rtls.lailab.online/api/v1/get_last_location_by_floor_id","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns the last known tag locations on the requested <code>floor_id</code>.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_location_history</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>The collection provides these fields: <code>floor_id</code>. Fields marked disabled in Postman are optional examples unless the purpose section states otherwise.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_last_location_by_floor_id"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"8faee0a1-3cb0-4aed-b7d6-24185aee1636"},{"name":"last location by tag","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"3fb338f8-91ee-4cb3-a513-cf51b377d937"}}],"id":"70440009-5a5a-4357-9988-966f156a9f30","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"tag_id","value":"[tag_id]","type":"text"}]},"url":"https://rtls.lailab.online/api/v1/get_last_location_by_tag_id","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns the last known location for <code>tag_id</code>. If <code>tag_id</code> is omitted, returns last-location records for all tags accessible to the authenticated staff account.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_location_history</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>The collection provides these fields: <code>tag_id</code>. Fields marked disabled in Postman are optional examples unless the purpose section states otherwise.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_last_location_by_tag_id"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"70440009-5a5a-4357-9988-966f156a9f30"},{"name":"get all tag last location","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"d5a88da2-d0dc-48ee-97ac-60e371868d90"}}],"id":"9b36e4d3-b42c-4bde-a814-f04a28498fe1","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[]},"url":"https://rtls.lailab.online/api/v1/get_all_tag_last_location","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns the last known location of every tag accessible to the authenticated staff account.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_location_history</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>Send the request using the body format configured in this collection.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_all_tag_last_location"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"9b36e4d3-b42c-4bde-a814-f04a28498fe1"},{"name":"last location by zone","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"e65e269a-526c-48f7-83c8-a30482267304"}}],"id":"928eb723-a971-4e48-9b98-3c5518f8a1ce","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"zone_id","value":"[ZONE_ID]","description":"<p>ZONE_ID</p>\n","type":"text"}]},"url":"https://rtls.lailab.online/api/v1/get_last_location_by_zone_id","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns the last known tag locations in the requested <code>zone_id</code>.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_location_history</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>The collection provides these fields: <code>zone_id</code>. Fields marked disabled in Postman are optional examples unless the purpose section states otherwise.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_last_location_by_zone_id"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"928eb723-a971-4e48-9b98-3c5518f8a1ce"},{"name":"get location by tag","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"32fbebeb-fb85-4e2c-b4aa-54700f1ef494"}}],"id":"9419dd1a-2fc4-4e69-b1f2-dd10194a185b","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"tag_id","value":"[tag_id]","description":"<p>TAG_ID</p>\n","type":"text"},{"key":"start_timestamp","value":"[start unitx timestamp in second]","description":"<p>start unitx timestamp in second</p>\n","type":"text"},{"key":"end_timestamp","value":"[end unitx timestamp in second]","description":"<p>end unitx timestamp in second</p>\n","type":"text"},{"key":"mode","value":"page","description":"<p>Optional. Set to page to enable cursor pagination. Leave disabled or omit for legacy full-response behavior.</p>\n","type":"text","disabled":true},{"key":"page_size","value":"auto","description":"<p>Optional. Use auto or a positive number. Numeric page_size skips count unless include_total=true.</p>\n","type":"text","disabled":true},{"key":"include_total","value":"true","description":"<p>Optional. Set true to include total_count. Requires a count preflight on the first page.</p>\n","type":"text","disabled":true},{"key":"cursor","value":"[next_cursor]","description":"<p>Optional. Use next_cursor from the previous page. Must match the same ID and time range.</p>\n","type":"text","disabled":true}]},"url":"https://rtls.lailab.online/api/v1/get_location_by_tag_id","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns location history for <code>tag_id</code> between <code>start_timestamp</code> and <code>end_timestamp</code>. Set <code>mode</code> to <code>page</code> to use cursor pagination; path-simplification options may also be supplied.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_location_history</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>The collection provides these fields: <code>tag_id</code>, <code>start_timestamp</code>, <code>end_timestamp</code>, <code>mode</code>, <code>page_size</code>, <code>include_total</code>, <code>cursor</code>. Fields marked disabled in Postman are optional examples unless the purpose section states otherwise.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_location_by_tag_id"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"9419dd1a-2fc4-4e69-b1f2-dd10194a185b"},{"name":"get location by floor","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"e61fb586-375c-4b2b-acaa-207ff5fbf63d"}}],"id":"9c8144e4-2ac5-4fd6-bb8a-e38f6b777ff4","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"floor_id","value":"[floor_id]","type":"text"},{"key":"start_timestamp","value":"[start unitx timestamp in second]","description":"<p>[start unitx timestamp in second]</p>\n","type":"text"},{"key":"end_timestamp","value":"[end unitx timestamp in second]","description":"<p>[end unitx timestamp in second]</p>\n","type":"text"},{"key":"mode","value":"page","description":"<p>Optional. Set to page to enable cursor pagination. Leave disabled or omit for legacy full-response behavior.</p>\n","type":"text","disabled":true},{"key":"page_size","value":"auto","description":"<p>Optional. Use auto or a positive number. Numeric page_size skips count unless include_total=true.</p>\n","type":"text","disabled":true},{"key":"include_total","value":"true","description":"<p>Optional. Set true to include total_count. Requires a count preflight on the first page.</p>\n","type":"text","disabled":true},{"key":"cursor","value":"[next_cursor]","description":"<p>Optional. Use next_cursor from the previous page. Must match the same ID and time range.</p>\n","type":"text","disabled":true}]},"url":"https://rtls.lailab.online/api/v1/get_location_by_floor_id","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns location history for <code>floor_id</code> between <code>start_timestamp</code> and <code>end_timestamp</code>. Set <code>mode</code> to <code>page</code> to use cursor pagination; path-simplification options may also be supplied.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_location_history</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>The collection provides these fields: <code>floor_id</code>, <code>start_timestamp</code>, <code>end_timestamp</code>, <code>mode</code>, <code>page_size</code>, <code>include_total</code>, <code>cursor</code>. Fields marked disabled in Postman are optional examples unless the purpose section states otherwise.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_location_by_floor_id"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"9c8144e4-2ac5-4fd6-bb8a-e38f6b777ff4"},{"name":"get tag timeline by floor","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"6b92d026-7183-4212-9f33-b82be1e0fa7d"}}],"id":"a6cdc1ee-5153-4f1b-b968-09b4c607b374","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"floor_id","value":"[floor_id]","type":"text"},{"key":"start_timestamp","value":"[start unitx timestamp in second]","description":"<p>[start unitx timestamp in second]</p>\n","type":"text"},{"key":"end_timestamp","value":"[end unitx timestamp in second]","description":"<p>[end unitx timestamp in second]</p>\n","type":"text"}]},"url":"https://rtls.lailab.online/api/v1/get_tag_timeline_by_floor_id","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Returns the tag timeline for <code>floor_id</code> between <code>start_timestamp</code> and <code>end_timestamp</code>.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_location_history</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>The collection provides these fields: <code>floor_id</code>, <code>start_timestamp</code>, <code>end_timestamp</code>. Fields marked disabled in Postman are optional examples unless the purpose section states otherwise.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","get_tag_timeline_by_floor_id"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"a6cdc1ee-5153-4f1b-b968-09b4c607b374"}],"id":"7b80bc4c-c728-46a1-af8a-5aa01cb56d33","description":"<p>Reads current and historical tag locations. These operations are limited to floors, zones, and tags accessible to the authenticated staff account.</p>\n","_postman_id":"7b80bc4c-c728-46a1-af8a-5aa01cb56d33"},{"name":"socket","item":[{"name":"gen socket topic","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"76371f59-bbe0-4149-b774-0029cc05fb41"}},{"listen":"test","script":{"type":"text/javascript","exec":["","// Save Socket.IO Message Guide variables.","let socketTopicResponse = {};","try { socketTopicResponse = pm.response.json(); } catch (error) {}","const socketTopicData = Array.isArray(socketTopicResponse) ? socketTopicResponse[0] : socketTopicResponse;","if (socketTopicData && socketTopicData.encrypt_topic) {","    pm.environment.set(\"encrypt_topic\", socketTopicData.encrypt_topic);","    pm.collectionVariables.set(\"encrypt_topic\", socketTopicData.encrypt_topic);","}","if (socketTopicData && socketTopicData.socket_token) {","    pm.environment.set(\"socket_token\", socketTopicData.socket_token);","    pm.collectionVariables.set(\"socket_token\", socketTopicData.socket_token);","    pm.environment.set(\"API_SOCKET_TOKEN\", socketTopicData.socket_token);","    pm.collectionVariables.set(\"API_SOCKET_TOKEN\", socketTopicData.socket_token);","}"],"id":"dbfb3276-a57e-431c-a6c2-79fe2df21cbc"}}],"id":"7097a58d-3b71-4757-9d8a-ea81fc010864","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"floorID","value":"[Floor ID]","description":"<p>Floor ID</p>\n","type":"text"}]},"url":"https://rtls.lailab.online/api/v1/gen_encrypt_topic","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Generates encrypted Socket.IO topic data for one floor ID or an array of floor IDs supplied in <code>floorID</code>. Every requested floor must be accessible to the authenticated staff account. <code>/api/v1/gen_encrypt_topic</code> is the canonical endpoint; the legacy <code>/gen_encrypt_topic</code> alias remains available for backward compatibility.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and authenticated staff access.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>The collection provides these fields: <code>floorID</code>. Fields marked disabled in Postman are optional examples unless the purpose section states otherwise.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","gen_encrypt_topic"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"7097a58d-3b71-4757-9d8a-ea81fc010864"},{"name":"get socket topic by tagid","event":[{"listen":"prerequest","script":{"type":"text/javascript","exec":["const apiAccessToken = pm.environment.get('API_ACCESS_TOKEN') || pm.collectionVariables.get('API_ACCESS_TOKEN');","","if (!apiAccessToken) {","    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');","}","","pm.request.headers.upsert({","    key: 'Authorization',","    value: `Bearer ${apiAccessToken}`","});"],"id":"08e0c1eb-e0fb-4228-a506-04d705091948"}},{"listen":"test","script":{"type":"text/javascript","exec":["","// Save Socket.IO Message Guide variables.","let socketTopicResponse = {};","try { socketTopicResponse = pm.response.json(); } catch (error) {}","const socketTopicData = Array.isArray(socketTopicResponse) ? socketTopicResponse[0] : socketTopicResponse;","if (socketTopicData && socketTopicData.encrypt_topic) {","    pm.environment.set(\"encrypt_topic\", socketTopicData.encrypt_topic);","    pm.collectionVariables.set(\"encrypt_topic\", socketTopicData.encrypt_topic);","}","if (socketTopicData && socketTopicData.socket_token) {","    pm.environment.set(\"socket_token\", socketTopicData.socket_token);","    pm.collectionVariables.set(\"socket_token\", socketTopicData.socket_token);","    pm.environment.set(\"API_SOCKET_TOKEN\", socketTopicData.socket_token);","    pm.collectionVariables.set(\"API_SOCKET_TOKEN\", socketTopicData.socket_token);","}"],"id":"06035d4c-119b-4678-87d8-d6b46214a378"}}],"id":"230c8d3c-e2c6-45da-8d02-84ef24a30139","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"tagID","value":"","description":"<p>tag ID</p>\n","type":"text"}]},"url":"https://rtls.lailab.online/api/v1/gen_tag_encrypt_topic_socket","description":"<h3 id=\"purpose\">Purpose</h3>\n<p>Generates encrypted Socket.IO topic data for the requested tag within the authenticated staff access scope.</p>\n<h3 id=\"authorization\">Authorization</h3>\n<p>Requires a valid bearer access token and <code>api_read_location_history</code>.</p>\n<h3 id=\"request-body\">Request body</h3>\n<p>The collection provides these fields: <code>tagID</code>. Fields marked disabled in Postman are optional examples unless the purpose section states otherwise.</p>\n<h3 id=\"response\">Response</h3>\n<p>Returns JSON data for a successful request. Invalid input, an expired or invalid token, insufficient permission, an inaccessible resource, or an internal error returns the corresponding non-2xx HTTP status.</p>\n","urlObject":{"path":["api","v1","gen_tag_encrypt_topic_socket"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"230c8d3c-e2c6-45da-8d02-84ef24a30139"}],"id":"59f8ea5d-cc1e-43ac-85dd-a84b58451b35","description":"<p>Generates encrypted Socket.IO topics and socket credentials for floors or tags within the authenticated staff access scope.</p>\n<h3 id=\"socketio-connection\">Socket.IO connection</h3>\n<ul>\n<li>URL: <code>https://socketx.lailab.online?token=</code></li>\n<li>Listen event: <code>clientBox</code></li>\n<li>Run an HTTP topic request first so Postman saves <code>socket_token</code> and <code>encrypt_topic</code>.</li>\n</ul>\n<h3 id=\"message-guide\">Message Guide</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Event</th>\n<th>Message</th>\n<th>Result</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>/join</code></td>\n<td><code>unai//tag</code></td>\n<td>Receive every Tag on the Floor</td>\n</tr>\n<tr>\n<td><code>/join</code></td>\n<td><code>unai//tag/</code></td>\n<td>Receive only the selected Tag</td>\n</tr>\n<tr>\n<td><code>/leave</code></td>\n<td><code>unai//tag</code></td>\n<td>Stop receiving every Tag on the Floor</td>\n</tr>\n<tr>\n<td><code>/leave</code></td>\n<td><code>unai//tag/</code></td>\n<td>Stop receiving the selected Tag</td>\n</tr>\n<tr>\n<td><code>/join</code></td>\n<td><code>unai//anchor</code></td>\n<td>Receive Anchors on the Floor</td>\n</tr>\n<tr>\n<td><code>/leave</code></td>\n<td><code>unai//anchor</code></td>\n<td>Stop receiving Anchors on the Floor</td>\n</tr>\n</tbody>\n</table>\n</div><p>In Postman Socket.IO, enter the value in the Message editor and select the matching event name beside Send.</p>\n","_postman_id":"59f8ea5d-cc1e-43ac-85dd-a84b58451b35"}],"variable":[{"key":"URL","value":"https://rtls.lailab.online"},{"key":"ACCESS_TOKEN","value":""},{"key":"REFRESH_TOKEN","value":""},{"key":"API_KEY","value":""},{"key":"STAFF_ID","value":"1"},{"key":"SESSION_COOKIE","value":"","description":"Express session cookie value for internal browser/session APIs, for example connect.sid=..."},{"key":"auth_secret_07d4"},{"key":"API_ACCESS_TOKEN","value":"","description":"Bearer token saved by /auth/gen_token and used by protected API requests."},{"key":"API_SOCKET_TOKEN","value":"","description":"Socket token saved by /auth/gen_token."},{"key":"SOCKET_URL","value":"https://socketx.lailab.online","description":"Public Socket.IO endpoint. Override this value for another deployment."},{"key":"socket_token","value":"","description":"Socket token saved automatically by authentication or topic-generation requests."},{"key":"encrypt_topic","value":"","description":"Encrypted Floor topic saved automatically by a topic-generation request."},{"key":"tag_id","value":"","description":"Tag database ID used by the tag topic request and the single-Tag Socket.IO room."}]}