{"info":{"_postman_id":"0fe6f5fc-fd4d-4fc7-8579-1b6ba1400d29","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":"0fe6f5fc-fd4d-4fc7-8579-1b6ba1400d29","publishedId":"2sBYAsyCVJ","public":true,"customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"},"publishDate":"2026-08-26T02:54:49.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\");","}"],"id":"4326541d-e5f9-42d3-b848-92c76ff3f8ba"}}],"id":"81d0fc3f-f22a-4152-8a52-ff1409b4514a","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":"81d0fc3f-f22a-4152-8a52-ff1409b4514a"},{"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":"c7c68f53-2bb9-4362-8d3a-e91a83102715"}}],"id":"9e278d24-35a7-4a06-9aab-74202729a5b2","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":"9e278d24-35a7-4a06-9aab-74202729a5b2"}],"id":"3efe6a83-7138-446f-8cc8-a0046d0ac510","description":"<p>Issues and rotates access and refresh tokens for API authentication.</p>\n","_postman_id":"3efe6a83-7138-446f-8cc8-a0046d0ac510"},{"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":"a088a61a-bb53-4274-89e6-556d075e66f9"}}],"id":"42fb3781-d1ed-46eb-aec7-076af5935b10","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":"42fb3781-d1ed-46eb-aec7-076af5935b10"}],"id":"8e4745b6-26ac-41c4-95d5-e585ac3e911a","description":"<p>Reads the current runtime status of gateways visible to the authenticated staff account.</p>\n","_postman_id":"8e4745b6-26ac-41c4-95d5-e585ac3e911a"},{"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":"ea1d1ead-a6d9-4962-a694-4cb14167e42b"}}],"id":"66058747-590e-4994-bb08-cc23506260e3","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":"66058747-590e-4994-bb08-cc23506260e3"},{"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":"5cb5281a-8eb4-421f-adca-27274c74edbb"}}],"id":"bc1b03d3-8cf0-4ec8-97ff-812399d97e31","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":"bc1b03d3-8cf0-4ec8-97ff-812399d97e31"},{"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":"ae10d043-341d-4df7-b924-848825446161"}}],"id":"d948140c-7818-45e4-9cdc-00c990912a57","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":"d948140c-7818-45e4-9cdc-00c990912a57"},{"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":"32cad925-da12-4378-9666-c9ffc0804f51"}}],"id":"c511fff2-5f4d-40c0-90b6-4de6d5a5dec0","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":"c511fff2-5f4d-40c0-90b6-4de6d5a5dec0"}],"id":"3619ae6e-1756-4fd7-83b6-48a3db8ef837","description":"<p>Reads places and place-level device-access assignments visible to the authenticated staff account.</p>\n","_postman_id":"3619ae6e-1756-4fd7-83b6-48a3db8ef837"},{"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":"ecea0786-0fdc-4475-9f5e-5f1d69e0a18b"}}],"id":"2ee4cb36-13f0-43a1-91a9-21fc9cddb054","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":"2ee4cb36-13f0-43a1-91a9-21fc9cddb054"},{"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":"262334d6-bec8-4501-86cf-db414b2cb731"}}],"id":"0eb16c63-a37e-4293-b670-76a4dd0aa4ab","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":"0eb16c63-a37e-4293-b670-76a4dd0aa4ab"},{"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":"30a29a63-e724-4b9b-9dbc-c2017f9a39d9"}}],"id":"593566bb-909d-42e6-ab6a-e706ea0b6645","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":"593566bb-909d-42e6-ab6a-e706ea0b6645"}],"id":"96c90bf6-90ad-484c-b6f4-4e55660d5fb2","description":"<p>Reads buildings visible to the authenticated staff account, optionally scoped by place or building ID.</p>\n","_postman_id":"96c90bf6-90ad-484c-b6f4-4e55660d5fb2"},{"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":"42ff6896-a344-4199-86fe-e37244b59960"}}],"id":"5705b1ef-d3d2-4aa5-a962-d0f4cc4c8187","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":"5705b1ef-d3d2-4aa5-a962-d0f4cc4c8187"},{"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":"370440b6-4d70-4ae8-adcd-8626c48954d0"}}],"id":"bf34f5cf-ac0e-43f7-9daa-2cb927b3a200","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":"bf34f5cf-ac0e-43f7-9daa-2cb927b3a200"},{"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":"58049a16-a2c9-4374-9afa-d272d2caa501"}}],"id":"d7966c13-5e6d-4258-81f8-32294f468116","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":"d7966c13-5e6d-4258-81f8-32294f468116"}],"id":"72bba238-0f26-4092-8a21-f3476dcb79d8","description":"<p>Reads floors visible to the authenticated staff account, optionally scoped by building or floor ID.</p>\n","_postman_id":"72bba238-0f26-4092-8a21-f3476dcb79d8"},{"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":"6f1963ee-ac52-4407-9764-37bd3206cc2c"}}],"id":"a55b005b-64cd-4b91-a7c1-7fed61b7dc5b","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":"a55b005b-64cd-4b91-a7c1-7fed61b7dc5b"},{"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":"42827dee-fdf7-4892-affc-9503bc0e27e6"}}],"id":"9cf14ccd-80bf-4777-84e8-dd5e71d4d75a","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":"9cf14ccd-80bf-4777-84e8-dd5e71d4d75a"},{"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":"cd475012-fcef-4c37-a005-77e421d2c949"}}],"id":"e702fb4c-c98d-4c17-a31c-266ea296e690","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":"e702fb4c-c98d-4c17-a31c-266ea296e690"},{"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":"c981fb03-31b5-4d38-92df-808687d96c27"}}],"id":"d98e3734-5739-4256-a8a1-593954052f3c","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":"d98e3734-5739-4256-a8a1-593954052f3c"}],"id":"afa99101-2a65-4739-b5ce-6fa5754e0ca2","description":"<p>Reads floor zones and shelf-zone metadata within the authenticated staff access scope.</p>\n","_postman_id":"afa99101-2a65-4739-b5ce-6fa5754e0ca2"},{"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":"850db64d-afe8-4198-baa8-d2802caf8b06"}}],"id":"77c10099-2ea4-4a3b-bb34-9f1921d51c2d","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":"77c10099-2ea4-4a3b-bb34-9f1921d51c2d"},{"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":"ed4a7466-9525-48d2-980e-fcdb9337743d"}}],"id":"a67cdb5c-befa-4356-b903-b9a17d115401","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":"a67cdb5c-befa-4356-b903-b9a17d115401"},{"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":"4749b3a1-bd6e-4a91-afdf-4fab38a555f4"}}],"id":"c8ce79ef-43e8-4b52-8861-27fa5564f25d","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":"c8ce79ef-43e8-4b52-8861-27fa5564f25d"}],"id":"6c11c248-1cd1-4406-ae32-cc5987e35996","description":"<p>Reads anchor metadata within the authenticated staff access scope.</p>\n","_postman_id":"6c11c248-1cd1-4406-ae32-cc5987e35996"},{"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":"789e3f50-a41d-40ca-abda-9844b3710aeb"}}],"id":"90d2e61e-a080-4645-bb3e-4bda3ac880a4","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":"90d2e61e-a080-4645-bb3e-4bda3ac880a4"},{"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":"170f9438-ddf0-4ffa-baef-84ecb6b123ec"}}],"id":"d5b527f0-a647-475d-8085-1e2bb89bff58","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":"d5b527f0-a647-475d-8085-1e2bb89bff58"},{"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":"6e4b89d5-46be-42f1-9220-c4d3665f477d"}}],"id":"7d76f49e-ee9b-4e4a-96c5-83d618e9bc2a","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":"7d76f49e-ee9b-4e4a-96c5-83d618e9bc2a"},{"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');\n\nif (!apiAccessToken) {\n    throw new Error('API_ACCESS_TOKEN is not set. Run /auth/gen_token first.');\n}\n\npm.request.headers.upsert({\n    key: 'Authorization',\n    value: `Bearer ${apiAccessToken}`\n});"]}}],"id":"a52faea9-02ce-48ca-a8ee-006eacad611d","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"id","value":"","description":"<p>Required positive database ID used to create or update the tag.</p>\n"},{"key":"tag_id","value":"","description":"<p>Beacon or hardware tag identifier stored on the tag record.</p>\n"},{"key":"label","value":"","description":"<p>Human-readable name or label for the tag.</p>\n"},{"key":"ui_display","value":"","description":"<p>Short display name shown in the user interface.</p>\n"},{"key":"major","value":"","description":"<p>Beacon major value used with the UUID and minor value.</p>\n"},{"key":"minor","value":"","description":"<p>Required when creating a new tag; optional when updating.</p>\n"},{"key":"uuid","value":"","description":"<p>Beacon UUID used with the major and minor values.</p>\n"},{"key":"manufacturer","value":"","description":"<p>Tag hardware manufacturer name.</p>\n","disabled":true},{"key":"volt_battery","value":"","description":"<p>Battery voltage reported by the tag.</p>\n","disabled":true},{"key":"firmware_version","value":"","description":"<p>Firmware version reported by the tag.</p>\n","disabled":true},{"key":"mac_address","value":"","description":"<p>MAC address of the tag hardware.</p>\n","disabled":true},{"key":"blink_period","value":"","description":"<p>Beacon blink or advertising period.</p>\n","disabled":true},{"key":"tx_ant_delay","value":"","description":"<p>Transmit antenna delay calibration value.</p>\n","disabled":true},{"key":"rx_ant_delay","value":"","description":"<p>Receive antenna delay calibration value.</p>\n","disabled":true},{"key":"device_type_id","value":"1","description":"<p>Database ID of the tag device type.</p>\n"},{"key":"x","value":"","description":"<p>Tag X coordinate in the configured place or map.</p>\n","disabled":true},{"key":"y","value":"","description":"<p>Tag Y coordinate in the configured place or map.</p>\n","disabled":true},{"key":"z","value":"","description":"<p>Tag Z coordinate or height in the configured place or map.</p>\n","disabled":true},{"key":"place_id","value":"1","description":"<p>Non-SuperAdmin callers must have access to this place.</p>\n"},{"key":"tagcol","value":"","description":"<p>Optional application-specific tag classification value.</p>\n","disabled":true},{"key":"device_id_thingsboard","value":"","description":"<p>ThingsBoard device identifier associated with the tag.</p>\n","disabled":true},{"key":"device_access_token_thingsboard","value":"","description":"<p>ThingsBoard access token for the associated device.</p>\n","disabled":true},{"key":"disable","value":"","description":"<p>Disable flag for the tag; use 0 for enabled and 1 for disabled.</p>\n","disabled":true},{"key":"path_id","value":"","description":"<p>Database ID of the path used for tag snapping.</p>\n","disabled":true},{"key":"status","value":"","description":"<p>Current active status of the tag.</p>\n","disabled":true},{"key":"method_id","value":"","description":"<p>Database ID of the positioning method assigned to the tag.</p>\n","disabled":true},{"key":"serial_number","value":"","description":"<p>Serial number printed on or reported by the tag hardware.</p>\n","disabled":true},{"key":"paired_with_id","value":"","description":"<p>Identifier of a tag paired with this tag, when applicable.</p>\n","disabled":true},{"key":"batt_percentage","value":"","description":"<p>Battery percentage reported by the tag.</p>\n","disabled":true},{"key":"batt_change_date","value":"","description":"<p>Date and time when the battery value last changed.</p>\n","disabled":true},{"key":"link_with_gateway_id","value":"","description":"<p>Database ID of the gateway linked to this tag.</p>\n","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":"a52faea9-02ce-48ca-a8ee-006eacad611d"},{"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":"54c69716-425e-481e-9386-6780894225f5"}}],"id":"e1aeef6f-2786-46c7-ac52-06508e9e309c","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":"e1aeef6f-2786-46c7-ac52-06508e9e309c"},{"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":"424917c8-f27b-40e8-984d-ef6414fc4c09"}}],"id":"441d2695-c263-4d57-a56c-98d7cb247044","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":"441d2695-c263-4d57-a56c-98d7cb247044"}],"id":"65c04ccd-bc68-43ec-b1ba-e6365b8ceb16","description":"<p>Reads tag and sensor metadata and creates tags within the authenticated staff access scope.</p>\n","_postman_id":"65c04ccd-bc68-43ec-b1ba-e6365b8ceb16"},{"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":"c7e1018f-7f72-4884-bd56-f5ee30662f4f"}}],"id":"a0ef41d0-b2fd-4902-8ba7-0e5064b18be3","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":"a0ef41d0-b2fd-4902-8ba7-0e5064b18be3"},{"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":"74b54b8a-fcc9-49ed-a938-984cab6182e4"}}],"id":"db134520-59a7-4f86-a3fb-50103941dab7","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":"db134520-59a7-4f86-a3fb-50103941dab7"},{"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":"f986239b-2c1d-41df-9639-776f21d18c2d"}}],"id":"bb07aa08-a61c-450b-b009-2a723746cb6d","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":"bb07aa08-a61c-450b-b009-2a723746cb6d"},{"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":"8b8dfc46-652b-4a0b-a0ae-ae91bd3400d2"}}],"id":"1db5859b-4325-47d1-b063-fb8b0232ac77","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":"1db5859b-4325-47d1-b063-fb8b0232ac77"}],"id":"b1048c9f-30e9-4ae5-bdda-9fce46bd9a78","description":"<p>Reads and manages tracked-user profiles within the authenticated staff access scope.</p>\n","_postman_id":"b1048c9f-30e9-4ae5-bdda-9fce46bd9a78"},{"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":"c3dace8e-979a-49ca-b406-aaac775f4872"}}],"id":"3c13672f-3bc0-4303-940c-1a04beafc5a6","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":"3c13672f-3bc0-4303-940c-1a04beafc5a6"}],"id":"9d8ab55a-dd60-4c27-b83c-023c8870edbf","description":"<p>Reads the user groups available within the authenticated staff access scope.</p>\n","_postman_id":"9d8ab55a-dd60-4c27-b83c-023c8870edbf"},{"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":"253a4379-2efe-4e4e-b737-aefa368c40c7"}}],"id":"dcdb2233-9d90-4f8c-9c14-7cdc2e53410f","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":"dcdb2233-9d90-4f8c-9c14-7cdc2e53410f"},{"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":"4c7307aa-046e-4297-9102-ff45f2251f43"}}],"id":"e32b1bd3-604d-4438-9e17-7ef4a13483a4","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":"e32b1bd3-604d-4438-9e17-7ef4a13483a4"},{"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":"de230c95-fdc4-4905-ad02-398483187f1f"}}],"id":"3881d151-a459-4160-a842-57985eb5c545","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":"3881d151-a459-4160-a842-57985eb5c545"},{"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":"f4407033-55b0-499f-b3fd-8f2a931201f8"}}],"id":"f14d1c32-bc74-4ce1-a7d6-27328b86f0e7","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":"f14d1c32-bc74-4ce1-a7d6-27328b86f0e7"},{"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":"d57c9c07-9540-4391-818b-9a6ea6622400"}}],"id":"4be801da-91ba-4584-b918-ee7b7cddfdaf","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":"4be801da-91ba-4584-b918-ee7b7cddfdaf"},{"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":"38c931e5-4edc-49a4-a149-f90bf00d3586"}}],"id":"b2733af7-e406-46be-949e-c493d64f1530","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":"b2733af7-e406-46be-949e-c493d64f1530"}],"id":"b2efd7be-7c1a-42a8-b663-96ee9f11e70a","description":"<p>Reads and manages staff accounts and staff roles. Management operations require staff-management permission.</p>\n","_postman_id":"b2efd7be-7c1a-42a8-b663-96ee9f11e70a"},{"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":"7782e26a-b9b0-4170-8355-bb7498dc0cb5"}}],"id":"23887a1f-cc3a-4836-8c15-16da7ed6e6ff","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":"23887a1f-cc3a-4836-8c15-16da7ed6e6ff"},{"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":"ff3c10be-96fb-46c9-8680-fb2c63dfb4d0"}}],"id":"70d13fe5-c3a3-45cb-a683-2428019d200a","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":"70d13fe5-c3a3-45cb-a683-2428019d200a"},{"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":"86af4a12-2347-487e-8107-9bbddc4e2dac"}}],"id":"ebcc8a74-2415-462c-b561-d74c39002c92","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":"ebcc8a74-2415-462c-b561-d74c39002c92"},{"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":"ff65af43-24ec-44ed-92f3-f66fa91d5a89"}}],"id":"ab4bfc82-0803-46ba-a5bd-7ccf8f0be15b","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":"ab4bfc82-0803-46ba-a5bd-7ccf8f0be15b"},{"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":"05d56b1e-cf6a-4318-8cc4-5215d3f9e6af"}}],"id":"86957aee-acff-461e-b608-ffc3d100b923","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":"86957aee-acff-461e-b608-ffc3d100b923"},{"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":"f6aaccd8-2cc7-4194-a37d-3d30ce182aad"}}],"id":"1e055fb4-211a-4f4c-9c3e-738c4f1691f8","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":"1e055fb4-211a-4f4c-9c3e-738c4f1691f8"},{"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":"503ac27f-db30-4297-8c19-e96a33c6b7e0"}}],"id":"ff60e053-e229-4560-9ea3-223b1711343e","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":"ff60e053-e229-4560-9ea3-223b1711343e"}],"id":"b671330a-64d7-4d71-bc0c-55ec983f9d54","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":"b671330a-64d7-4d71-bc0c-55ec983f9d54"},{"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":"5c6c2008-eacc-4c33-bb0b-8af055edf307"}}],"id":"854e1f57-4b01-4aa8-9381-dc9cad4d05de","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/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.</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":["gen_encrypt_topic"],"host":["https://rtls.lailab.online"],"query":[],"variable":[]}},"response":[],"_postman_id":"854e1f57-4b01-4aa8-9381-dc9cad4d05de"},{"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":"26c4875c-29ac-4336-9576-99c498854708"}}],"id":"41f2e27c-94c0-4cb4-918e-0c6a76d60063","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"tagID","value":"[tag ID]","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_manage_device_data</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":"41f2e27c-94c0-4cb4-918e-0c6a76d60063"}],"id":"23af7f3b-b08d-4c7c-a906-4a33ef4c4291","description":"<p>Generates encrypted Socket.IO topics and socket credentials for floors or tags within the authenticated staff access scope.</p>\n","_postman_id":"23af7f3b-b08d-4c7c-a906-4a33ef4c4291"}],"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."}]}