Exaba pricing engine technical surface

Exaba Pricing Engine

Technical route at /tech. Callable endpoints stay under /api/.... This page shows the setup assumptions, curl examples, the generated 48-month spreadsheet, the JSON report, and the JavaScript-engine table and framework graph demos.

Setup assumption presets

Open Branded TCO App Download Demo Spreadsheet Open Demo JSON Report Open JavaScript Engine

Setup Assumptions

Changing the scenario buttons updates these assumptions and the demo links above.

{
  "scenarioName": "Exaba Demo Scenario 1",
  "months": 48,
  "startingTB": 500.0,
  "monthlyGrowthTB": 10.0,
  "revenuePerTBPerMonth": 20.0,
  "costPerTBPerMonth": 2.0,
  "currency": "USD",
  "pricingModel": "fixed",
  "numberOfSites": 1,
  "prepaymentThresholdTB": 1200.0,
  "prepaymentAmountTB": 1000.0,
  "commitmentPricePerTbPerMonth": 2.5,
  "flexiblePricePerTbPerMonth": 3.5,
  "progressiveSplits": [
    {
      "tb": 5000.0,
      "pricePerTBPerMonth": 3.5
    },
    {
      "tb": 25000.0,
      "pricePerTBPerMonth": 2.625
    },
    {
      "tb": 70000.0,
      "pricePerTBPerMonth": 1.75
    },
    {
      "tb": null,
      "pricePerTBPerMonth": 0.875
    }
  ],
  "introductoryFreeMonths": 3,
  "discountedPriceThresholdTB": 2000.0,
  "discountedPriceFactor": 0.5,
  "serverMonthlyCost": 4500.0,
  "switchMonthlyCost": 500.0,
  "serversPerRack": 6,
  "rackCostPerMonth": 0.0,
  "powerCostPerServerPerMonth": 250.0,
  "peopleManagedServicePerMonth": 395.8333333,
  "connectivityPerMonth": 700.0,
  "otherFixedMonthlyCost": 1000.0,
  "otherVariableMonthlyPerTb": 0.0,
  "minimumServers": 3,
  "rawCapacityPerServerTB": 2880.0,
  "capacityHeadroomFactor": 0.8
}

Curl: Test Report

Post assumptions to the report API and get the canonical monthly attribute model back as JSON.

curl -s https://tco.exaba.com/api/v1/test \
  -H 'content-type: application/json' \
  -d '{
  "scenario": {
    "capacityHeadroomFactor": 0.8,
    "commitmentPricePerTbPerMonth": 2.5,
    "connectivityPerMonth": 700.0,
    "costPerTBPerMonth": 2.0,
    "currency": "USD",
    "discountedPriceFactor": 0.5,
    "discountedPriceThresholdTB": 2000.0,
    "flexiblePricePerTbPerMonth": 3.5,
    "introductoryFreeMonths": 3,
    "minimumServers": 3,
    "monthlyGrowthTB": 10.0,
    "months": 48,
    "numberOfSites": 1,
    "otherFixedMonthlyCost": 1000.0,
    "otherVariableMonthlyPerTb": 0.0,
    "peopleManagedServicePerMonth": 395.8333333,
    "powerCostPerServerPerMonth": 250.0,
    "prepaymentAmountTB": 1000.0,
    "prepaymentThresholdTB": 1200.0,
    "pricingModel": "fixed",
    "progressiveSplits": [
      {
        "pricePerTBPerMonth": 3.5,
        "tb": 5000.0
      },
      {
        "pricePerTBPerMonth": 2.625,
        "tb": 25000.0
      },
      {
        "pricePerTBPerMonth": 1.75,
        "tb": 70000.0
      },
      {
        "pricePerTBPerMonth": 0.875,
        "tb": null
      }
    ],
    "rackCostPerMonth": 0.0,
    "rawCapacityPerServerTB": 2880.0,
    "revenuePerTBPerMonth": 20.0,
    "scenarioName": "Exaba Demo Scenario 1",
    "serverMonthlyCost": 4500.0,
    "serversPerRack": 6,
    "startingTB": 500.0,
    "switchMonthlyCost": 500.0
  }
}'

Curl: Setup Artifacts

Post the same assumptions to the setup API to generate standalone JavaScript and spreadsheet artifacts on disk.

curl -s https://tco.exaba.com/api/v1/setup \
  -H 'content-type: application/json' \
  -d '{
  "artifacts": {
    "outputDir": "artifacts/root-demo"
  },
  "scenario": {
    "capacityHeadroomFactor": 0.8,
    "commitmentPricePerTbPerMonth": 2.5,
    "connectivityPerMonth": 700.0,
    "costPerTBPerMonth": 2.0,
    "currency": "USD",
    "discountedPriceFactor": 0.5,
    "discountedPriceThresholdTB": 2000.0,
    "flexiblePricePerTbPerMonth": 3.5,
    "introductoryFreeMonths": 3,
    "minimumServers": 3,
    "monthlyGrowthTB": 10.0,
    "months": 48,
    "numberOfSites": 1,
    "otherFixedMonthlyCost": 1000.0,
    "otherVariableMonthlyPerTb": 0.0,
    "peopleManagedServicePerMonth": 395.8333333,
    "powerCostPerServerPerMonth": 250.0,
    "prepaymentAmountTB": 1000.0,
    "prepaymentThresholdTB": 1200.0,
    "pricingModel": "fixed",
    "progressiveSplits": [
      {
        "pricePerTBPerMonth": 3.5,
        "tb": 5000.0
      },
      {
        "pricePerTBPerMonth": 2.625,
        "tb": 25000.0
      },
      {
        "pricePerTBPerMonth": 1.75,
        "tb": 70000.0
      },
      {
        "pricePerTBPerMonth": 0.875,
        "tb": null
      }
    ],
    "rackCostPerMonth": 0.0,
    "rawCapacityPerServerTB": 2880.0,
    "revenuePerTBPerMonth": 20.0,
    "scenarioName": "Exaba Demo Scenario 1",
    "serverMonthlyCost": 4500.0,
    "serversPerRack": 6,
    "startingTB": 500.0,
    "switchMonthlyCost": 500.0
  }
}'

48-Month Table

The table is empty until you click the render button. If you switch scenarios after the table is already visible, the page automatically re-runs the selected scenario through the JavaScript engine and updates the displayed HTML table.

Table not loaded yet.

Framework Graph Demos

Each graph button lazy-loads its chart framework from a CDN, runs the selected scenario through the JavaScript engine, and renders one chart per pricing row so you can compare Plotly.js, D3.js, and Chart.js against the same monthly values.

Graphs not loaded yet.

Example HTML Page

This is the standalone HTML pattern for the selected preset: fetch the JavaScript engine, evaluate it, build the model from the scenario, then iterate across months and attributes with getValue(attribute, month).

<!doctype html>
<html lang="en">
  <body>
    <table id="pricing-table"></table>
    <script>
      async function main() {
        const engineSource = await fetch("https://tco.exaba.com/api/v1/library/javascript").then((response) => response.text());
        globalThis.eval(engineSource);

        const scenario = {
  "scenarioName": "Exaba Demo Scenario 1",
  "months": 48,
  "startingTB": 500.0,
  "monthlyGrowthTB": 10.0,
  "revenuePerTBPerMonth": 20.0,
  "costPerTBPerMonth": 2.0,
  "currency": "USD",
  "pricingModel": "fixed",
  "numberOfSites": 1,
  "prepaymentThresholdTB": 1200.0,
  "prepaymentAmountTB": 1000.0,
  "commitmentPricePerTbPerMonth": 2.5,
  "flexiblePricePerTbPerMonth": 3.5,
  "progressiveSplits": [
    {
      "tb": 5000.0,
      "pricePerTBPerMonth": 3.5
    },
    {
      "tb": 25000.0,
      "pricePerTBPerMonth": 2.625
    },
    {
      "tb": 70000.0,
      "pricePerTBPerMonth": 1.75
    },
    {
      "tb": null,
      "pricePerTBPerMonth": 0.875
    }
  ],
  "introductoryFreeMonths": 3,
  "discountedPriceThresholdTB": 2000.0,
  "discountedPriceFactor": 0.5,
  "serverMonthlyCost": 4500.0,
  "switchMonthlyCost": 500.0,
  "serversPerRack": 6,
  "rackCostPerMonth": 0.0,
  "powerCostPerServerPerMonth": 250.0,
  "peopleManagedServicePerMonth": 395.8333333,
  "connectivityPerMonth": 700.0,
  "otherFixedMonthlyCost": 1000.0,
  "otherVariableMonthlyPerTb": 0.0,
  "minimumServers": 3,
  "rawCapacityPerServerTB": 2880.0,
  "capacityHeadroomFactor": 0.8
};
        const model = ExabaTco.createPricingModel(scenario);
        const table = document.getElementById("pricing-table");
        const months = model.getMonths();
        const attributes = model.getAttributes();

        const headerRow = document.createElement("tr");
        ["Attribute", "Unit", ...months.map((month) => "Month " + month)].forEach((label) => {
          const cell = document.createElement("th");
          cell.textContent = label;
          headerRow.appendChild(cell);
        });

        const thead = document.createElement("thead");
        thead.appendChild(headerRow);
        table.appendChild(thead);

        const tbody = document.createElement("tbody");
        attributes.forEach((attribute) => {
          const row = document.createElement("tr");
          const labelCell = document.createElement("td");
          labelCell.textContent = attribute.label;
          row.appendChild(labelCell);

          const unitCell = document.createElement("td");
          unitCell.textContent = attribute.unit;
          row.appendChild(unitCell);

          months.forEach((month) => {
            const valueCell = document.createElement("td");
            valueCell.textContent = model.getValue(attribute.key, month);
            row.appendChild(valueCell);
          });

          tbody.appendChild(row);
        });

        table.appendChild(tbody);
      }

      main();
    </script>
  </body>
</html>