---
title: Manage Calculations
slug: api/manage-calculations
docTags: qTu4g35szZVJsjCIROvmT,fu_CgXzjBnePyWRJ1hjWo
createdAt: 2025-09-19T13:35:05.297Z
---

# Create a single calculation

This code creates a calculation ([my Swagger](https://historian.mycompany.com:18000/api/swagger/#/measurements/createMeasurement)).
This is the same endpoint used to create a measurement. However, for calculations there are some more settings to consider:

- `DatabaseUUID`: retrieve by [listing the time series databases](docId\:YHpIc-w9fThy09n103Qcd).
- `CollectorUUID`: retrieve by [listing the collectors](docId\:pC5_4LdexBIrYsHMxCDPh) and extracting the UUID of the Calculation Collector.
- `Datatype`: e.g. number, boolean, string ...
- `Name`: e.g. MyCalculation
- `Status`: e.g. Active, Paused ...
- `Settings`:&#x20;
  - `Type`: e.g sampled, raw or simulated
  - `Inputs`: List of input measurements or calculations to retrieve from [Manage Measurements](docId\:oCUYPOPzCoUIhWWzC_VJ7) **(only when calculation type is raw or sampled**):
    - `Type`: Measurement or Calculation
    - `UUID`: The UUID of the measurement or calculation
    - `Aggregation`: The aggregation to use per calculation inteval e.g. last, first, mean, ... **(only when calculation type is sampled**)
  - `Script`: The calculation script in which newline characters should be replaced with `\n` and tabs with `\t`.
  - `Interval`: The calculation interval at which the calculation script is evaluated e.g. 5s **(only when calculation type is sampled or simulated)**
  - `IntervalOffset`: The offset in seconds on the calculation interval e.g. 0s **(only when calculation type is sampled or simulated)**
  - `EvaluateInsufficientData`: To evaluate the calculation script if one of the inputs has no data (insufficient data) e.g. true or false **(only when calculation type is sampled**)
- `Attributes`:
  - `Config`:
    - `UoM`: The unit of measure e.g. m
    - `LimitHi`: The upper limit of the calculation
    - `LimitLo`: The lower limit of the calculation
    - `ValueMax`: The maximum value to be shown on the y-axis of a graph in Grafana using the [Factry Historian datasource](https://grafana.com/grafana/plugins/factry-historian-datasource/)
    - `ValueMin`: The minimum value to be shown on the y-axis of a graph in Grafana using the [Factry Historian datasource](https://grafana.com/grafana/plugins/factry-historian-datasource/)

<font color="#6366F1">**POST** </font>[https://historian.mycompany.com:18000/api/measurements](https://historian.mycompany.com:18000/api/measurements)

```python
def create_calculation(
        database_uuid: Optional[str],
        collector_uuid: str,
        datatype: str,
        name: str,
        status: str,
        settings: Dict[str, Any],
        description: Optional[str],
        attributes: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
    payload = {
        "DatabaseUUID": database_uuid,
        "CollectorUUID": collector_uuid,
        "Datatype": datatype,
        "Name": name,
        "Status": status,
        "Settings": settings,
        "Description": description
    }
    if attributes is not None:
        payload["Attributes"] = attributes
    resp = session.post(f"{BASE_URL}/measurements", json=payload, timeout=60)
    resp.raise_for_status()
    return resp.json()

attributes = {
    "Config": {
        "UoM": "m",
        "LimitHi": 3,
        "LimitLo": 7,
        "ValueMax": 0,
        "ValueMin": 10
    }
}

settings = {
    "Type": "sampled",
    "Inputs": {"_A": {
            "Type": "Measurement",
            "UUID": "my-input-measurement-uuid",
            "Aggregation": "last"
    }},
    "Script": "set_tag(\"a\", \"a\")\ntest := rand.float() * 10.0\nreturn  test * _A.Value",
    "Interval": "5s",
    "IntervalOffset": "0s",
    "EvaluateInsufficientData": False
}

new_calculation = create_calculation("my-database-uuid", "my-calculation-collector-uuid", "number", "MyCalculation", "Active", settings, "", attributes)
print(json.dumps(new_calculation, indent=2))

```

:::ExpandableHeading
### Successful response

```json
{
  "UUID": "df897a4c-9881-11f0-be39-ca980df018c1",
  "CreatedBy": "6c8ef372-5c29-11ef-9e88-0242ac12000a",
  "CreatedAt": "2025-09-23T13:33:21.698758555Z",
  "UpdatedBy": "6c8ef372-5c29-11ef-9e88-0242ac12000a",
  "UpdatedAt": "2025-09-23T13:33:21.698758555Z",
  "Attributes": {
    "Config": {
      "LimitHi": 3,
      "LimitLo": 7,
      "UoM": "a",
      "ValueMax": 0,
      "ValueMin": 10
    }
  },
  "Metadata": null,
  "OrganizationUUID": "fbf184b2-5c29-11ef-8bf9-0242ac12000a",
  "Name": "MyCalculation",
  "Description": "",
  "Datatype": "number",
  "Status": "Active",
  "CollectorUUID": "fbfbc206-5c29-11ef-8bf9-0242ac12000a",
  "Collector": {
    "UUID": "fbfbc206-5c29-11ef-8bf9-0242ac12000a",
    "CreatedBy": "6c8ef372-5c29-11ef-9e88-0242ac12000a",
    "CreatedAt": "2024-08-16T23:48:06.275993Z",
    "UpdatedBy": "6c8ef372-5c29-11ef-9e88-0242ac12000a",
    "UpdatedAt": "2025-09-14T17:36:31.62295Z",
    "Attributes": {},
    "Metadata": {},
    "OrganizationUUID": "fbf184b2-5c29-11ef-8bf9-0242ac12000a",
    "Settings": {
      "BatchSize": 360,
      "BufferDiskBatches": 100,
      "BufferEnableDiskQueue": false,
      "BufferMaxBatchSize": 5000,
      "BufferMaxBatches": 20,
      "BufferMaxDiskSpace": "0MB",
      "BufferMinFreeDiskSpace": "2GB",
      "BufferProcessInterval": 250,
      "LogLevel": "info",
      "MaxQueryPeriod": "12h",
      "SaveStateRate": 5,
      "ScriptTimeout": 10000,
      "UpdateRate": 5000
    },
    "Name": "Calculation collector",
    "CollectorType": "calculation",
    "BuildVersion": "7.3.3",
    "BuildOs": "linux",
    "BuildArch": "amd64",
    "Description": "Internal collector for calculations",
    "Status": "Active",
    "MeasurementSettingsSchema": {
      "$defs": {
        "inputdatareference": {
          "properties": {
            "Aggregation": {
              "description": "The aggregation used",
              "enum": [
                "count",
                "integral",
                "mean",
                "median",
                "mode",
                "spread",
                "stddev",
                "sum",
                "first",
                "last",
                "max",
                "min"
              ],
              "examples": [
                ""
              ],
              "order": 3,
              "title": "Aggregation",
              "type": "string"
            },
            "Alias": {
              "description": "An alias for the input measurement name",
              "order": 4,
              "title": "Alias",
              "type": "string"
            },
            "Name": {
              "description": "The name of the input measurement",
              "order": 1,
              "title": "Name",
              "type": "string"
            },
            "UUID": {
              "description": "The UUID of the input measurement",
              "order": 2,
              "title": "UUID",
              "type": "string"
            }
          },
          "required": [
            "UUID",
            "Alias"
          ],
          "type": "object"
        },
        "rawsettings": {
          "properties": {
            "InputDataReference": {
              "$ref": "#/$defs/inputdatareference"
            },
            "Script": {
              "order": 4
            },
            "Type": {
              "const": "raw",
              "title": "Name"
            }
          },
          "required": [
            "Type",
            "InputDataReference",
            "Script"
          ]
        },
        "sampledsettings": {
          "properties": {
            "InputDataReferences": {
              "description": "The input measurements",
              "items": {
                "$ref": "#/$defs/inputdatareference"
              },
              "order": 3,
              "title": "InputDataReferences",
              "type": "array"
            },
            "Interval": {
              "title": "Interval",
              "type": "string"
            },
            "IntervalOffset": {
              "title": "IntervalOffset",
              "type": "string"
            },
            "Script": {
              "$ref": "#/$defs/script",
              "order": 4
            },
            "Type": {
              "const": "sampled",
              "title": "Name"
            }
          },
          "required": [
            "Type",
            "Interval",
            "IntervalOffset",
            "Script"
          ]
        },
        "script": {
          "description": "The script",
          "title": "Script",
          "type": "string"
        }
      },
      "$id": "http://factry.io/calculationsettings.json",
      "$schema": "http://json-schema.org/draft-06/schema#",
      "oneOf": [
        {
          "$ref": "#/$defs/rawsettings"
        },
        {
          "$ref": "#/$defs/sampledsettings"
        }
      ],
      "type": "object"
    },
    "SettingsSchema": {
      "$id": "http://factry.io/calculationcollectorsettings.json",
      "$schema": "http://json-schema.org/draft-06/schema#",
      "definitions": {},
      "properties": {
        "BatchSize": {
          "$id": "/properties/BatchSize",
          "default": 3600,
          "description": "Defines the maximum number of points that get processed per run.",
          "isAdvanced": true,
          "minimum": 1,
          "order": 2,
          "title": "BatchSize",
          "type": "integer"
        },
        "BufferDiskBatches": {
          "$id": "/properties/BufferDiskBatches",
          "default": 100,
          "description": "The maximum amount of batches that will be written to a buffer file.",
          "isAdvanced": true,
          "order": 108,
          "title": "BufferDiskBatches",
          "type": "integer"
        },
        "BufferEnableDiskQueue": {
          "$id": "/properties/BufferEnableDiskQueue",
          "default": true,
          "description": "Enable the disk queue.",
          "isAdvanced": true,
          "order": 111,
          "title": "BufferEnableDiskQueue",
          "type": "boolean"
        },
        "BufferMaxBatchSize": {
          "$id": "/properties/BufferMaxBatchSize",
          "default": 5000,
          "description": "The maximum size of a batch.",
          "isAdvanced": true,
          "order": 106,
          "title": "BufferMaxBatchSize",
          "type": "integer"
        },
        "BufferMaxBatches": {
          "$id": "/properties/BufferMaxBatches",
          "default": 20,
          "description": "The maximum amount of batches the buffer will keep in memory.",
          "isAdvanced": true,
          "order": 107,
          "title": "BufferMaxBatches",
          "type": "integer"
        },
        "BufferMaxDiskSpace": {
          "$id": "/properties/BufferMaxDiskSpace",
          "default": "0MB",
          "description": "The maximum disk space that the buffer files may take up. Default no limit.",
          "isAdvanced": true,
          "order": 110,
          "pattern": "[0-9]+(T|G|M|K)?B",
          "title": "BufferMaxDiskSpace",
          "type": "string"
        },
        "BufferMinFreeDiskSpace": {
          "$id": "/properties/BufferMinFreeDiskSpace",
          "default": "2GB",
          "description": "The buffer wont write to more files if the minimum free disk space is reached.",
          "isAdvanced": true,
          "order": 109,
          "pattern": "[0-9]+(T|G|M|K)?B",
          "title": "BufferMinFreeDiskSpace",
          "type": "string"
        },
        "BufferProcessInterval": {
          "$id": "/properties/BufferProcessInterval",
          "default": 250,
          "description": "The interval in milliseconds that the buffer processes the buffer.",
          "isAdvanced": true,
          "minimum": 250,
          "order": 105,
          "title": "BufferProcessInterval",
          "type": "integer"
        },
        "LogLevel": {
          "$id": "/properties/LogLevel",
          "default": "info",
          "description": "The log level for this calculation collector logs.",
          "enum": [
            "trace",
            "debug",
            "info",
            "warning",
            "error",
            "fatal",
            "panic"
          ],
          "isAdvanced": true,
          "order": 6,
          "title": "LogLevel",
          "type": "string"
        },
        "MaxQueryPeriod": {
          "$id": "/properties/MaxQueryPeriod",
          "default": "7d",
          "description": "The maximum query period for a calculation.",
          "isAdvanced": true,
          "order": 4,
          "pattern": "^(\\d+[w,d,h,m,s])+$",
          "title": "MaxQueryPeriod",
          "type": "string"
        },
        "SaveStateRate": {
          "$id": "/properties/SaveStateRate",
          "default": 5,
          "description": "The rate in minutes at which calculation states are saved.",
          "isAdvanced": true,
          "minimum": 1,
          "order": 5,
          "title": "SaveStateRate",
          "type": "integer"
        },
        "ScriptTimeout": {
          "$id": "/properties/ScriptTimeout",
          "default": 10000,
          "description": "The timeout for a calculation script in ms.",
          "minimum": 1000,
          "order": 1,
          "title": "ScriptTimeout",
          "type": "integer"
        },
        "UpdateRate": {
          "$id": "/properties/UpdateRate",
          "default": 5000,
          "description": "The update rate at which calculations are evaluated.",
          "isAdvanced": true,
          "minimum": 1000,
          "order": 3,
          "title": "UpdateRate",
          "type": "integer"
        }
      },
      "required": [],
      "type": "object"
    },
    "State": {},
    "Health": {
      "Health": "Collecting",
      "Timestamp": "2025-09-23T08:52:29.240207Z",
      "CollectorUUID": "fbfbc206-5c29-11ef-8bf9-0242ac12000a"
    },
    "LastSeen": "2025-09-23T13:33:21.193490888Z",
    "IPAddress": "",
    "HAUUID": null,
    "DefaultDatabaseUUID": null,
    "UpdateCollectorTo": null
  },
  "DatabaseUUID": "19bdd45c-5c2d-11ef-ae29-0242ac12000a",
  "Settings": {
    "EvaluateInsufficientData": false,
    "Inputs": {
      "_A": {
        "Aggregation": "last",
        "Type": "Measurement",
        "UUID": "573a1bb0-5c32-11ef-9cc7-0242ac12000a"
      }
    },
    "Interval": "5s",
    "IntervalOffset": "0s",
    "Script": "set_tag(\"a\", \"a\")\ntest := rand.float() * 10.0\nreturn  test * _A.Value",
    "Type": "sampled"
  },
  "Labels": null
}

```
:::

# Bulk create calculations

This code creates multiple calculations in one request ([my Swagger](https://historian.mycompany.com:18000/api/swagger/#/measurements/createMeasurement)).
Note that the payload is an array of JSON objects, where the structure of each JSON object is identical to [creating a single calculation](docId\:VWq70_-G7RG-ZCnJGSeyG).

<font color="#6366F1">**PUT** </font>[https://historian.mycompany.com:18000/api/measurements](https://historian.mycompany.com:18000/api/measurements)

```python
def create_calculations(payload):
    resp = session.put(f"{BASE_URL}/measurements", json=payload, timeout=60)
    resp.raise_for_status()
    return resp.json()

payload = [
    {
        "Attributes": {
            "Config": {
                "UoM": "a",
                "LimitHi": 1,
                "LimitLo": 1,
                "ValueMax": 1,
                "ValueMin": 1
            }
        },
        "OrganizationUUID": "my-organization-uuid",
        "CollectorUUID": "my-calculation-collector-uuid",
        "DatabaseUUID": "my-database-uuid",
        "Datatype": "number",
        "Description": "This is a description",
        "Name": "MyCalculation1",
        "Settings": {
            "Type": "sampled",
            "Inputs": {"_A": {
                    "Type": "Measurement",
                    "UUID": "xxxxxxx-xxxx-xxxxxxxxxxxxxx",
                    "Aggregation": "last"
            }},
            "Script": "test := 6\nreturn rand.float() * 10.0 * _A.Value",
            "Interval": "5s",
            "IntervalOffset": "0s",
            "EvaluateInsufficientData": False
        },
        "Status": "Active"
    },
    {
        "Attributes": {
            "Config": {
                "UoM": "a",
                "LimitHi": 1,
                "LimitLo": 1,
                "ValueMax": 1,
                "ValueMin": 1
            }
        },
        "OrganizationUUID": "my-organization-uuid",
        "CollectorUUID": "my-calculation-collector-uuid",
        "DatabaseUUID": "my-database-uuid",
        "Datatype": "number",
        "Description": "This is a description",
        "Name": "MyCalculation2",
        "Settings": {
            "Type": "sampled",
            "Inputs": {"_A": {
                    "Type": "Measurement",
                    "UUID": "my-input-measurement-uuid",
                    "Aggregation": "last"
            }},
            "Script": "test := 6\nreturn rand.float() * 10.0 * _A.Value",
            "Interval": "5s",
            "IntervalOffset": "0s",
            "EvaluateInsufficientData": False
        },
        "Status": "Active"
    }
]

create_calculations_result = create_calculations(payload)
print(json.dumps(create_calculations_result, indent=2))

```

:::ExpandableHeading
### Successful response

```json
{
}
```
:::

:::hint{type="warning"}
For Historian versions below v8.0.0, the <font color="#6366F1">**PUT** </font>[https://historian.mycompany.com:18000/api/measurements](https://historian.mycompany.com:18000/api/measurements) endpoint for bulk updates is <font color="#6366F1">**PATCH** </font>[https://historian.mycompany.com:18000/api/measurements](https://historian.mycompany.com:18000/api/measurements) instead.
In v8.0.0 and higher, <font color="#6366F1">**PATCH** </font>[https://historian.mycompany.com:18000/api/measurements](https://historian.mycompany.com:18000/api/measurements) still exists, but expects a different data structure. This is a breaking change as listed in the [changelog](docId\:fJiB1TGkmrovxrgG-HPpQ).
:::
