{
  "info": {
    "name": "IntelliFront BI Public API",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "_postman_id": "51dddada-2cd9-47e3-9cde-2711f1dc5de3",
    "description": "# IntelliFront BI API collection\n\nUse this collection with IntelliFront BI Environment Template. It contains 42 practical requests for authentication, native analytics, customer reporting access, configured report jobs and operational inspection. The API reference documents the complete public API.\n\n## Setup\nImport both JSON files, select the environment and set baseUrl to your API root, including its configured port (normally 50255) and an IIS application path when applicable. IFBI installs both the web application and API in IIS. The web application normally uses HTTPS on port 443; API requests must use the separate API URL. The placeholder shows an API configured for HTTPS; confirm the API protocol, port and path with your administrator. Do not append /api or a trailing slash. Replace the example.com host. Enter credentials in local environment values.\n\n## Authenticate\nUse Authenticate an IFBI user for user-context operations, including canvases and favorites. Domain login and X-OTP are supported as optional form fields. Authenticate a service client uses client_credentials; the registered client must have the SERVICE claim and a compatible identity for the requested endpoint. Both token requests use form encoding and No Auth. Their scripts clear stale token values and capture access_token and expiry on success. Other protected requests inherit the collection bearer token. The collection does not automatically renew tokens.\n\n## Start with native analytics\nFind an existing KPI ID, set kpi_id, send Get a KPI configuration, then Calculate the selected native KPI. The read request caches the selected configuration; the calculation builds the exact KpiDataModel from it. Review returned Data as a string. The read does not silently choose the first KPI or dataset.\n\n## Configuration and execution\nRun requests individually. Canvas creation, favorites, KPI goal updates, dataset import and manual Gizmo execution change state or can process/deliver business data. Read each request description and fill the named variables first. Full-model updates preserve the fetched configuration but require coordination with other editors.\n\nFor a configured report job, set gizmo_id, inspect its availability/state, then submit Queue one configured Gizmo. The script saves manual_run_request_id. Queue submission is asynchronous; this identifier is not a PBRS ExecutionId and no PBRS execution-status endpoint is used. Queue disappearance and absence of errors do not prove delivery. Reconcile an uncertain submission before retrying.\n\n## Local values\nCredentials, tokens and cached KPI/dataset definitions belong in local values. Do not export populated environments. Read and capture scripts clear their own previous result before a new request. They do not infer customer scope or grant access. No live installation credentials or real customer identifiers are included in these files.\n\nDocumentation: https://intellifront-bi.readme.io/docs/getting-started\nAPI reference: https://intellifront-bi.readme.io/reference\nRecipes: https://intellifront-bi.readme.io/recipes"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{access_token}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://intellifront.example.com:50255",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "01 Authentication",
      "description": "Authenticate a user or registered service client. Token requests use the IFBI form-encoded /api/token contract.",
      "item": [
        {
          "name": "Authenticate an IFBI user",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/x-www-form-urlencoded"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/token",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "token"
              ]
            },
            "description": "Set username and password. Set domain_user=true for configured domain login. Enable X-OTP only when required. A user token is needed for endpoints that require the current user ID.\n\nObtain an access token and send it on protected requests as `Authorization: Bearer <access_token>`. Send token requests as application/x-www-form-urlencoded. The default token lifetime in the reviewed configuration is 30 minutes; the effective lifetime depends on deployment configuration.\n\nSupported grants:\n- `password`: username and password; set domain_user=true for domain login. Supply X-OTP as a request parameter when required.\n- `client_credentials`: registered client ID and secret, supplied as form fields or HTTP Basic credentials. The client must have the SERVICE claim.\n- `adsso`: authdata in the query string.\n- `customauth`: session_id in the query string; the remote IP address is also used.\n- `msgraphsso`: access_token in the token parameters.\n\nReference: https://intellifront-bi.readme.io/reference/authentication_gettoken",
            "auth": {
              "type": "noauth"
            },
            "body": {
              "mode": "urlencoded",
              "urlencoded": [
                {
                  "key": "grant_type",
                  "value": "password",
                  "type": "text"
                },
                {
                  "key": "username",
                  "value": "{{username}}",
                  "type": "text"
                },
                {
                  "key": "password",
                  "value": "{{password}}",
                  "type": "text"
                },
                {
                  "key": "domain_user",
                  "value": "{{domain_user}}",
                  "type": "text"
                },
                {
                  "key": "X-OTP",
                  "value": "{{otp}}",
                  "type": "text",
                  "disabled": true,
                  "description": "Enable and set otp when this user requires a current one-time passcode."
                }
              ]
            }
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "[\"access_token\", \"token_expires_in\", \"token_expires_at\"].forEach(name => pm.environment.unset(name));",
                  "requireValue(\"username\"); requireValue(\"password\");",
                  "if (![\"true\", \"false\"].includes(value(\"domain_user\"))) throw new Error(\"domain_user must be true or false\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}",
                  "if (pm.response.code === 200) {",
                  "    const token = pm.response.json();",
                  "    const valid = typeof token.access_token === \"string\" && token.access_token.trim().length > 0 && Number.isFinite(token.expires_in) && token.expires_in > 0;",
                  "    pm.test(\"A token and positive expiry were returned\", function () { pm.expect(valid).to.eql(true); });",
                  "    if (valid) {",
                  "        pm.environment.set(\"access_token\", token.access_token);",
                  "        pm.environment.set(\"token_expires_in\", String(token.expires_in));",
                  "        pm.environment.set(\"token_expires_at\", new Date(Date.now() + token.expires_in * 1000).toISOString());",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Authenticate a service client",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/x-www-form-urlencoded"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/token",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "token"
              ]
            },
            "description": "Set a registered client ID and secret. The client must have the SERVICE claim. This identity does not automatically supply the current user ID required by user-context operations.\n\nObtain an access token and send it on protected requests as `Authorization: Bearer <access_token>`. Send token requests as application/x-www-form-urlencoded. The default token lifetime in the reviewed configuration is 30 minutes; the effective lifetime depends on deployment configuration.\n\nSupported grants:\n- `password`: username and password; set domain_user=true for domain login. Supply X-OTP as a request parameter when required.\n- `client_credentials`: registered client ID and secret, supplied as form fields or HTTP Basic credentials. The client must have the SERVICE claim.\n- `adsso`: authdata in the query string.\n- `customauth`: session_id in the query string; the remote IP address is also used.\n- `msgraphsso`: access_token in the token parameters.\n\nReference: https://intellifront-bi.readme.io/reference/authentication_gettoken",
            "auth": {
              "type": "noauth"
            },
            "body": {
              "mode": "urlencoded",
              "urlencoded": [
                {
                  "key": "grant_type",
                  "value": "client_credentials",
                  "type": "text"
                },
                {
                  "key": "client_id",
                  "value": "{{client_id}}",
                  "type": "text"
                },
                {
                  "key": "client_secret",
                  "value": "{{client_secret}}",
                  "type": "text"
                }
              ]
            }
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "[\"access_token\", \"token_expires_in\", \"token_expires_at\"].forEach(name => pm.environment.unset(name));",
                  "requireValue(\"client_id\"); requireValue(\"client_secret\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}",
                  "if (pm.response.code === 200) {",
                  "    const token = pm.response.json();",
                  "    const valid = typeof token.access_token === \"string\" && token.access_token.trim().length > 0 && Number.isFinite(token.expires_in) && token.expires_in > 0;",
                  "    pm.test(\"A token and positive expiry were returned\", function () { pm.expect(valid).to.eql(true); });",
                  "    if (valid) {",
                  "        pm.environment.set(\"access_token\", token.access_token);",
                  "        pm.environment.set(\"token_expires_in\", String(token.expires_in));",
                  "        pm.environment.set(\"token_expires_at\", new Date(Date.now() + token.expires_in * 1000).toISOString());",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "02 Discover native content",
      "description": "Read inventories and choose authorised IDs manually. No script selects the first resource or assumes customer scope.",
      "item": [
        {
          "name": "List datasets",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Dataset/All",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Dataset",
                "All"
              ]
            },
            "description": "Inspect the response and select the intended resource. Native dashboards have IsIntellifrontDashboard=true. Dataset and current-user canvas lists are bare arrays; dashboard and KPI lists are wrapped in Data. The canvas request needs a user identity.\n\nGets all datasets.\n\nReference: https://intellifront-bi.readme.io/reference/dataset_getdatasetsdata_get"
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "List dashboards",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Dashboard/All",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Dashboard",
                "All"
              ]
            },
            "description": "Inspect the response and select the intended resource. Native dashboards have IsIntellifrontDashboard=true. Dataset and current-user canvas lists are bare arrays; dashboard and KPI lists are wrapped in Data. The canvas request needs a user identity.\n\ngets all DashboardModels\n\nReference: https://intellifront-bi.readme.io/reference/dashboard_getall_get"
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "List KPIs",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Kpi/All",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Kpi",
                "All"
              ]
            },
            "description": "Inspect the response and select the intended resource. Native dashboards have IsIntellifrontDashboard=true. Dataset and current-user canvas lists are bare arrays; dashboard and KPI lists are wrapped in Data. The canvas request needs a user identity.\n\nRetrieves all KpiModels\n\nAssociated permissions: KPI Management. Effective access depends on your identity and installation configuration.\n\nReference: https://intellifront-bi.readme.io/reference/kpi_getall_get"
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "List canvases for the current user",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Canvas/GetAllForUser",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Canvas",
                "GetAllForUser"
              ]
            },
            "description": "Inspect the response and select the intended resource. Native dashboards have IsIntellifrontDashboard=true. Dataset and current-user canvas lists are bare arrays; dashboard and KPI lists are wrapped in Data. The canvas request needs a user identity.\n\n\n\nReference: https://intellifront-bi.readme.io/reference/canvas_getallforuser_get"
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "03 Datasets",
      "description": "Inspect configuration, related dashboards and refresh history; export and reuse a definition with an approved connection.",
      "item": [
        {
          "name": "Get a dataset configuration",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Dataset/{{dataset_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Dataset",
                "{{dataset_id}}"
              ]
            },
            "description": "Set dataset_id. Dataset detail is a bare configuration object, history a bare array, and related dashboards a bare ListModel with NativeDashboards IDs. These calls do not export general dataset rows or force a refresh.\n\nGets the Dataset data.\n\nReference: https://intellifront-bi.readme.io/reference/dataset_getdatasetdata_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"dataset_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Get related dashboards",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Dataset/getrelateddashboards/{{dataset_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Dataset",
                "getrelateddashboards",
                "{{dataset_id}}"
              ]
            },
            "description": "Set dataset_id. Dataset detail is a bare configuration object, history a bare array, and related dashboards a bare ListModel with NativeDashboards IDs. These calls do not export general dataset rows or force a refresh.\n\n\n\nReference: https://intellifront-bi.readme.io/reference/dataset_getrelateddashboards_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"dataset_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Get dataset refresh history",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Dataset/GetRefreshHistory/{{dataset_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Dataset",
                "GetRefreshHistory",
                "{{dataset_id}}"
              ]
            },
            "description": "Set dataset_id. Dataset detail is a bare configuration object, history a bare array, and related dashboards a bare ListModel with NativeDashboards IDs. These calls do not export general dataset rows or force a refresh.\n\n\n\nReference: https://intellifront-bi.readme.io/reference/dataset_getdatasetrefreshhistory_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"dataset_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Export and cache a dataset definition",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Dataset/Export/{{dataset_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Dataset",
                "Export",
                "{{dataset_id}}"
              ]
            },
            "description": "Caches the exported configuration locally as dataset_definition and records its source ID. Review query, schedule, file paths and data access before importing. This is a definition, not rendered reporting output.\n\n\n\nReference: https://intellifront-bi.readme.io/reference/dataset_export_post"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"dataset_id\");",
                  "pm.environment.unset(\"dataset_definition\"); pm.environment.unset(\"dataset_definition_source_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}",
                  "if (pm.response.code === 200) {",
                  " const definition = pm.response.json();",
                  " const valid = definition && typeof definition === \"object\" && !Array.isArray(definition) && !definition.IsError && typeof definition.Name === \"string\";",
                  " pm.test(\"A dataset definition was returned\", function () { pm.expect(Boolean(valid)).to.eql(true); });",
                  " if (valid) { pm.environment.set(\"dataset_definition\", JSON.stringify(definition)); pm.environment.set(\"dataset_definition_source_id\", pm.variables.get(\"dataset_id\")); }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Import the cached dataset with another connection",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Dataset/Import",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Dataset",
                "Import"
              ]
            },
            "description": "Creates a dataset and may process its data. First export the intended dataset. Set target_account_id, database_type_id and new_dataset_name. Review the cached definition and its dependencies. The script JSON-encodes datasetJson correctly and retains the new imported_dataset_id without replacing dataset_id. Reconcile an uncertain timeout before retrying.\n\n\n\nReference: https://intellifront-bi.readme.io/reference/dataset_importdataset_post",
            "body": {
              "mode": "raw",
              "raw": "{{dataset_import_body}}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "pm.environment.unset(\"imported_dataset_id\");",
                  "const source = requireGuid(\"dataset_id\");",
                  "if (source.toLowerCase() !== requireGuid(\"dataset_definition_source_id\").toLowerCase()) throw new Error(\"Export the selected dataset again before importing.\");",
                  "const definition = JSON.parse(requireValue(\"dataset_definition\"));",
                  "definition.Name = requireValue(\"new_dataset_name\");",
                  "pm.variables.set(\"dataset_import_body\", JSON.stringify({datasetJson: JSON.stringify(definition), accountId: requireGuid(\"target_account_id\"), databaseTypeId: requireGuid(\"database_type_id\")}));"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}",
                  "if (pm.response.code === 200) {",
                  " const result = pm.response.json();",
                  " const valid = result && typeof result.Id === \"string\" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result.Id);",
                  " pm.test(\"An imported dataset ID was returned\", function () { pm.expect(Boolean(valid)).to.eql(true); });",
                  " if (valid) pm.environment.set(\"imported_dataset_id\", result.Id);",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "04 Dashboards",
      "description": "Inspect native reporting configuration, access groups, cache timestamps and definition XML.",
      "item": [
        {
          "name": "Get a dashboard configuration",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Dashboard/{{dashboard_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Dashboard",
                "{{dashboard_id}}"
              ]
            },
            "description": "Set dashboard_id to the IFBI dashboard ID. Inspect Data in the response. A cache timestamp is not proof of source-record freshness.\n\nGet a Dashboard\n\nReference: https://intellifront-bi.readme.io/reference/dashboard_get_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"dashboard_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Get dashboard cache timestamp",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Dashboard/GetDashboardCacheLastRefreshDate/{{dashboard_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Dashboard",
                "GetDashboardCacheLastRefreshDate",
                "{{dashboard_id}}"
              ]
            },
            "description": "Set dashboard_id to the IFBI dashboard ID. Inspect Data in the response. A cache timestamp is not proof of source-record freshness.\n\n\n\nReference: https://intellifront-bi.readme.io/reference/dashboard_getdashboardcachelastrefreshdate_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"dashboard_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Get dashboard groups",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Dashboard/{{dashboard_id}}/Groups",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Dashboard",
                "{{dashboard_id}}",
                "Groups"
              ]
            },
            "description": "Set dashboard_id to the IFBI dashboard ID. Inspect Data in the response. A cache timestamp is not proof of source-record freshness.\n\nGets asynchronously the Groups associated with a KPI\n\nReference: https://intellifront-bi.readme.io/reference/dashboard_getgroupsbydashboardid_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"dashboard_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Export a native dashboard definition",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Dashboard/Export/{{dashboard_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Dashboard",
                "Export",
                "{{dashboard_id}}"
              ]
            },
            "description": "Returns native dashboard definition XML as a string in Data. It does not render a PDF, image or Excel workbook. Review the definition before reusing it with other datasets or connections.\n\nAssociated permissions: Dashboard Management. Effective access depends on your identity and installation configuration.\n\nReference: https://intellifront-bi.readme.io/reference/dashboard_export_post"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"dashboard_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "05 KPIs",
      "description": "Read an existing native KPI before calculating its result or changing its goal. Cached configuration is local environment data.",
      "item": [
        {
          "name": "Get a KPI configuration",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Kpi/{{kpi_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Kpi",
                "{{kpi_id}}"
              ]
            },
            "description": "Set kpi_id. Caches this exact KPI configuration for the calculation and goal-update requests. A failed read clears the old cache.\n\nGet a KPI\n\nReference: https://intellifront-bi.readme.io/reference/kpi_getkpi_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"kpi_id\");",
                  "pm.environment.unset(\"kpi_configuration\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}",
                  "if (pm.response.code === 200) {",
                  " const result = pm.response.json();",
                  " const kpi = result && !result.IsError ? result.Data : null;",
                  " const matches = kpi && typeof kpi.Id === \"string\" && kpi.Id.toLowerCase() === String(pm.variables.get(\"kpi_id\")).toLowerCase();",
                  " pm.test(\"The selected KPI configuration was returned\", function () { pm.expect(Boolean(matches)).to.eql(true); });",
                  " if (matches) pm.environment.set(\"kpi_configuration\", JSON.stringify(kpi));",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "List KPI aggregates",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Kpi/GetKPIAggregates",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Kpi",
                "GetKPIAggregates"
              ]
            },
            "description": "Use aggregate IDs returned by this installation rather than inventing them.\n\nGet Kpi Aggregates\n\nReference: https://intellifront-bi.readme.io/reference/kpi_getkpiaggregates_get"
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "List KPI units",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Kpi/GetKPIUnits",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Kpi",
                "GetKPIUnits"
              ]
            },
            "description": "Inspect the available units for native KPI configuration.\n\nGet Kpi Units\n\nReference: https://intellifront-bi.readme.io/reference/kpi_getkpiunits_get"
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Get KPI groups",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Kpi/{{kpi_id}}/Groups",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Kpi",
                "{{kpi_id}}",
                "Groups"
              ]
            },
            "description": "Returns group associations in Data. Associations alone do not prove all effective permissions or customer data isolation.\n\nGets asynchronously the Groups associated with a KPI\n\nReference: https://intellifront-bi.readme.io/reference/kpi_getgroupsbykpiid_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"kpi_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Calculate the selected native KPI",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Kpi/Result",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Kpi",
                "Result"
              ]
            },
            "description": "First send Get a KPI configuration for kpi_id. Builds DatasetId, DatasetColumn, AggregateId and optional RoundingAmount from that configuration. Returns a string in Data. Does not extract a Power BI visual or configure an alert.\n\nReturns KPI run result\n\nReference: https://intellifront-bi.readme.io/reference/kpi_getkpiresult_post",
            "body": {
              "mode": "raw",
              "raw": "{{kpi_result_body}}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "const kpi = JSON.parse(requireValue(\"kpi_configuration\"));",
                  "if (!kpi || typeof kpi.Id !== \"string\" || kpi.Id.toLowerCase() !== requireGuid(\"kpi_id\").toLowerCase()) throw new Error(\"Get the selected KPI configuration again first.\");",
                  "const payload = {};",
                  "[\"DatasetId\", \"DatasetColumn\", \"AggregateId\"].forEach(key => { if (!kpi[key]) throw new Error(\"KPI is missing \" + key); payload[key] = kpi[key]; });",
                  "if (kpi.RoundingAmount !== null && kpi.RoundingAmount !== undefined) payload.RoundingAmount = kpi.RoundingAmount;",
                  "pm.variables.set(\"kpi_result_body\", JSON.stringify(payload));"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}",
                  "if (pm.response.code === 200) {",
                  " const result = pm.response.json();",
                  " pm.test(\"KPI Data is a string\", function () { pm.expect(typeof result.Data).to.eql(\"string\"); });",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Update the selected KPI goal",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Kpi/Save",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Kpi",
                "Save"
              ]
            },
            "description": "Changes the existing KPI. First get its current configuration, set kpi_goal to the approved finite number, and coordinate with other editors. Preserves the fetched model and changes Goal only. Read the KPI back afterwards. The goal does not itself create a workflow or email alert.\n\nsaves a given KpiModel model to the Kpi table\n\nAssociated permissions: KPI Management. Effective access depends on your identity and installation configuration.\n\nReference: https://intellifront-bi.readme.io/reference/kpi_save_post",
            "body": {
              "mode": "raw",
              "raw": "{{kpi_update_body}}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "const kpi = JSON.parse(requireValue(\"kpi_configuration\"));",
                  "if (!kpi || typeof kpi.Id !== \"string\" || kpi.Id.toLowerCase() !== requireGuid(\"kpi_id\").toLowerCase()) throw new Error(\"Get the selected KPI configuration again first.\");",
                  "const rawGoal = requireValue(\"kpi_goal\");",
                  "const goal = Number(rawGoal);",
                  "if (!Number.isFinite(goal)) throw new Error(\"kpi_goal must be a finite number.\");",
                  "kpi.Goal = goal;",
                  "pm.variables.set(\"kpi_update_body\", JSON.stringify(kpi));"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "06 Canvases",
      "description": "Assemble existing content for an approved audience and manage the signed-in user’s preference. Use a user token.",
      "item": [
        {
          "name": "Get a canvas",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Canvas/{{canvas_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Canvas",
                "{{canvas_id}}"
              ]
            },
            "description": "Set canvas_id. Returns a bare Canvas object. This read shape is not the complete save/update model and does not expose a direct UserIds list.\n\n\n\nReference: https://intellifront-bi.readme.io/reference/canvas_getbyid_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"canvas_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Create a canvas for an existing group",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Canvas/Save",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Canvas",
                "Save"
              ]
            },
            "description": "Creates a canvas and captures its ID as canvas_id. Set canvas_name, dashboard_id, kpi_id and group_id. Underlying content and customer-data permissions must already be correct. Uses one dashboard, one KPI, one group, no direct user assignments and AutoRefresh=false. Repeating the request can create duplicate content.\n\n\n\nReference: https://intellifront-bi.readme.io/reference/canvas_save_post",
            "body": {
              "mode": "raw",
              "raw": "{{canvas_create_body}}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "pm.environment.unset(\"canvas_id\");",
                  "const payload = {Name: requireValue(\"canvas_name\"), Description: \"Reporting for an approved customer group\", DashboardIds: [requireGuid(\"dashboard_id\")], KpiIds: [requireGuid(\"kpi_id\")], GroupIds: [requireGuid(\"group_id\")], UserIds: [], AutoRefresh: false, RefreshInterval: 30};",
                  "pm.variables.set(\"canvas_create_body\", JSON.stringify(payload));"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}",
                  "if (pm.response.code === 200) {",
                  " const result = pm.response.json();",
                  " const valid = result && !result.IsError && typeof result.Data === \"string\" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result.Data);",
                  " pm.test(\"A canvas ID was returned\", function () { pm.expect(Boolean(valid)).to.eql(true); });",
                  " if (valid) pm.environment.set(\"canvas_id\", result.Data);",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Set the current user’s favorite canvas",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Canvas/SetFavoriteForUser",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Canvas",
                "SetFavoriteForUser"
              ]
            },
            "description": "Changes the signed-in user’s favorite. Set canvas_id to an accessible canvas. Server determines the user identity. HTTP 200 can have no response body. Read the favorite back to verify. Change IsFavorite to false to remove it.\n\n\n\nReference: https://intellifront-bi.readme.io/reference/canvas_setfavoriteforuser_post",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"CanvasId\": \"{{canvas_id}}\",\n  \"IsFavorite\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"canvas_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Get the current user’s favorite canvas",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Canvas/GetFavoriteCanvasForUser",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Canvas",
                "GetFavoriteCanvasForUser"
              ]
            },
            "description": "Returns a bare GUID string. Compare with canvas_id after saving the preference. Does not grant access or configure another user’s preference.\n\n\n\nReference: https://intellifront-bi.readme.io/reference/canvas_getfavoritekpiforuser_get"
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "07 Users and groups",
      "description": "Inspect the authenticated user, membership and group configuration without changing access.",
      "item": [
        {
          "name": "Get current user information",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/User/GetBasicCurrentUserInfo",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "User",
                "GetBasicCurrentUserInfo"
              ]
            },
            "description": "Uses a user token and returns the current user information as a bare object. Do not export personal or credential-related fields into shared examples.\n\n\n\nReference: https://intellifront-bi.readme.io/reference/user_getbasiccurrentuserinfo_get"
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "List groups",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Group/All",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Group",
                "All"
              ]
            },
            "description": "Returns a bare array. Choose the approved group manually and set group_id.\n\nGets the groups.\n\nReference: https://intellifront-bi.readme.io/reference/group_getgroups_get"
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Get a group",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Group/{{group_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Group",
                "{{group_id}}"
              ]
            },
            "description": "Returns a bare GroupModel.\n\nGet a Group\n\nReference: https://intellifront-bi.readme.io/reference/group_getgroup_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"group_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Get group members",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Group/GroupUsers/{{group_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Group",
                "GroupUsers",
                "{{group_id}}"
              ]
            },
            "description": "Returns a bare array of user models. Treat returned identity and credential-related information as restricted local data.\n\nGets the groups users.\n\nReference: https://intellifront-bi.readme.io/reference/group_getgroupusers_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"group_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Get groups for a selected user",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Group/UserGroups/{{user_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Group",
                "UserGroups",
                "{{user_id}}"
              ]
            },
            "description": "Set user_id. Returns a bare group array. This operation has no bearer requirement in the published contract and explicitly uses No Auth.\n\nGets the user groups.\n\nReference: https://intellifront-bi.readme.io/reference/group_getusergroups_get",
            "auth": {
              "type": "noauth"
            }
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"user_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "08 Configured report jobs",
      "description": "Inspect an existing Gizmo and submit one on-demand execution. Queue submission does not confirm completion or delivery.",
      "item": [
        {
          "name": "List Gizmo identifiers",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/GizmoNew/All",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "GizmoNew",
                "All"
              ]
            },
            "description": "The public response schema is a wrapped ListModel, not a bare Gizmo array. Inspect Data.Gizmos, then set gizmo_id to the intended configured job.\n\nGet all Gizmos\n\nAssociated permissions: Gizmo Management. Effective access depends on your identity and installation configuration.\n\nReference: https://intellifront-bi.readme.io/reference/gizmo_getall_get"
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Get a configured Gizmo",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/GizmoNew/{{gizmo_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "GizmoNew",
                "{{gizmo_id}}"
              ]
            },
            "description": "Inspect the existing configured report job and its settings before requesting execution.\n\nGet a Gizmo\n\nAssociated permissions: Gizmo Management. Effective access depends on your identity and installation configuration.\n\nReference: https://intellifront-bi.readme.io/reference/gizmo_get_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"gizmo_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Check a Gizmo’s API availability and state",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Service/IsAPIAvailable/{{gizmo_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Service",
                "IsAPIAvailable",
                "{{gizmo_id}}"
              ]
            },
            "description": "Inspect nested Response.IsError, Enabled and GizmoIsDeleted. Confirms responsive API and reported job state, not overall execution-service or destination health.\n\nGets a OK ServiceCheckModel response that the API is listening.If Gizmo Id is passed, system checks to see if gizmo is not deleted\n\nReference: https://intellifront-bi.readme.io/reference/service_isapiavailable_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"gizmo_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Queue one configured Gizmo",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/GizmoNew/AddGizmoToManuallyRun",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "GizmoNew",
                "AddGizmoToManuallyRun"
              ]
            },
            "description": "Can execute reports and deliver output through configured destinations. First check the intended job’s configuration and state. Saves the returned request GUID as manual_run_request_id. No automatic polling or retry. Reconcile uncertain outcomes before resubmitting.\n\nsaves a given gizmo to Run on Demand table\n\nAssociated permissions: Gizmo Execution. Effective access depends on your identity and installation configuration.\n\nReference: https://intellifront-bi.readme.io/reference/gizmo_addgizmotomanuallyrun_post",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"GizmoId\": \"{{gizmo_id}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "pm.environment.unset(\"manual_run_request_id\"); requireGuid(\"gizmo_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}",
                  "if (pm.response.code === 200) {",
                  " const result = pm.response.json();",
                  " const valid = result && !result.IsError && typeof result.Data === \"string\" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result.Data);",
                  " pm.test(\"A manual-run request ID was returned\", function () { pm.expect(Boolean(valid)).to.eql(true); });",
                  " if (valid) pm.environment.set(\"manual_run_request_id\", result.Data);",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "09 Monitoring and troubleshooting",
      "description": "Inspect API, queue and latest-error evidence. Queue IDs are not assumed to equal Gizmo or manual-run request IDs.",
      "item": [
        {
          "name": "Check API availability",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Service/IsAPIAvailable",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Service",
                "IsAPIAvailable"
              ]
            },
            "description": "Inspect the endpoint-specific response shape. Queue endpoints return arrays in Data. Broader queue access requires an appropriate identity. Queue disappearance or no returned error is not proof of report completion or delivery.\n\nGets a OK ServiceCheckModel response that the API is listening.If Gizmo Id is passed, system checks to see if gizmo is not deleted\n\nReference: https://intellifront-bi.readme.io/reference/service_isapiavailable_get_2"
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Inspect the current user’s Gizmo queue",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Service/GetAllGizmosInQueueForUser",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Service",
                "GetAllGizmosInQueueForUser"
              ]
            },
            "description": "Inspect the endpoint-specific response shape. Queue endpoints return arrays in Data. Broader queue access requires an appropriate identity. Queue disappearance or no returned error is not proof of report completion or delivery.\n\n\n\nReference: https://intellifront-bi.readme.io/reference/service_getallgizmosinqueueforuser_get"
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Inspect the administrative Gizmo queue",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Service/GetAllGizmosInQueue",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Service",
                "GetAllGizmosInQueue"
              ]
            },
            "description": "Inspect the endpoint-specific response shape. Queue endpoints return arrays in Data. Broader queue access requires an appropriate identity. Queue disappearance or no returned error is not proof of report completion or delivery.\n\n\n\nReference: https://intellifront-bi.readme.io/reference/service_getgizmoqueue_get"
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Get a Gizmo’s latest recorded error",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Error/GetLatestErrorLogForGizmo/{{gizmo_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Error",
                "GetLatestErrorLogForGizmo",
                "{{gizmo_id}}"
              ]
            },
            "description": "The latest error may predate the request being investigated. Compare timestamps with your application submission record and confirm the destination outcome separately. Restrict diagnostic details.\n\n\n\nReference: https://intellifront-bi.readme.io/reference/administration_getlatesterrorlogforgizmo_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"gizmo_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    },
    {
      "name": "10 Schedules and workflows",
      "description": "Read existing configuration before planning time-based or event-driven automation. These requests do not create or execute a workflow.",
      "item": [
        {
          "name": "List schedules",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Schedule/All",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Schedule",
                "All"
              ]
            },
            "description": "Inspect existing schedules and set schedule_id to an intended IFBI GUID, not a PBRS numeric schedule identifier.\n\nGets all Schedules\n\nReference: https://intellifront-bi.readme.io/reference/schedule_getall_get"
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Get a schedule",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Schedule/{{schedule_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Schedule",
                "{{schedule_id}}"
              ]
            },
            "description": "Inspect the saved schedule model and its resource relationship. This request does not execute the schedule.\n\nGets a specific Schedule object\n\nReference: https://intellifront-bi.readme.io/reference/schedule_get_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"schedule_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "List workflows",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Workflow/All",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Workflow",
                "All"
              ]
            },
            "description": "Inspect existing workflows, then choose workflow_id manually.\n\ngets all WorkflowModels\n\nAssociated permissions: Workflow Management. Effective access depends on your identity and installation configuration.\n\nReference: https://intellifront-bi.readme.io/reference/workflow_getall_get"
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Get a workflow",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/api/Workflow/{{workflow_id}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "api",
                "Workflow",
                "{{workflow_id}}"
              ]
            },
            "description": "Inspect feed, action, schedule and enabled settings before planning a change. Saving configuration and executing actions are separate outcomes.\n\nGet a Workflow\n\nAssociated permissions: Workflow Management. Effective access depends on your identity and installation configuration.\n\nReference: https://intellifront-bi.readme.io/reference/workflow_get_get"
          },
          "response": [],
          "event": [
            {
              "listen": "prerequest",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "function value(name) { return String(pm.variables.get(name) ?? \"\"); }",
                  "function requireValue(name) {",
                  "    const result = value(name);",
                  "    if (!result.trim()) throw new Error(\"Set \" + name + \" in the selected environment first.\");",
                  "    return result;",
                  "}",
                  "function requireGuid(name) {",
                  "    const result = requireValue(name);",
                  "    if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(result) || /^0{8}-0{4}-0{4}-0{4}-0{12}$/.test(result)) {",
                  "        throw new Error(name + \" must be a non-empty resource GUID from this installation.\");",
                  "    }",
                  "    return result;",
                  "}",
                  "requireGuid(\"workflow_id\");"
                ]
              }
            },
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "pm.test(\"HTTP request succeeded\", function () {",
                  "    pm.expect(pm.response.code).to.be.within(200, 299);",
                  "});",
                  "if (pm.response.code >= 200 && pm.response.code < 300 && pm.response.text().trim()) {",
                  "    const result = pm.response.json();",
                  "    if (result && typeof result === \"object\" && !Array.isArray(result) && Object.prototype.hasOwnProperty.call(result, \"IsError\")) {",
                  "        pm.test(\"API wrapper does not report an error\", function () { pm.expect(result.IsError).not.to.eql(true); });",
                  "    }",
                  "}"
                ]
              }
            }
          ]
        }
      ]
    }
  ],
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "const base = String(pm.variables.get(\"baseUrl\") || \"\");",
          "if (!/^https?:\\/\\//i.test(base) || /\\/$/.test(base) || /[?#]/.test(base) || /example\\.com/i.test(base)) {",
          "    throw new Error(\"Set baseUrl to your actual IFBI API root, including its configured port (normally 50255) and any IIS application path, without /api, a trailing slash, query or fragment.\");",
          "}"
        ]
      }
    }
  ]
}
