---
title: Manage Measurements
slug: api-v7/manage-measurements
docTags: 
createdAt: 2025-09-18T16:28:03.423Z
---

# Create measurements

This code creates a measurement by providing ([my Swagger](https://historian.mycompany.com:18000/api/swagger/#/measurements/createMeasurement)):&#x20;

- `DatabaseUUID`: retrieve by [listing the time series databases](docId:64SUMJC8mtVAUv2Wzv13S).
- `CollectorUUID`: retrieve by [listing the collectors](docId\:XyILd8uEb7AS2Mb-qxt3i).
- `Datatype`: e.g. number, boolean, string ...
- `Name`: Tank1\_Temperature
- `Status`: e.g. Active, Paused ...

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

:::hint{type="info"}
Via <font color="#6366F1">**POST**</font> [https://historian.mycompany.com:18000/api/measurements/excel](https://historian.mycompany.com:18000/api/measurements/excel), an Excel file can be uploaded to bulk create/update measurements.
:::

```python
def create_measurement(database_uuid, collector_uuid, datatype, name, status):
    payload = {
        "DatabaseUUID": database_uuid,
        "CollectorUUID": collector_uuid,
        "Datatype": datatype,
        "Name": name,
        "Status": status
    }
    resp = session.post(f"{BASE_URL}/measurements", json=payload, timeout=30)
    resp.raise_for_status()
    return resp.json()

# fill in the database and collector UUID before executing
new_measurement = create_measurement("my-database-uuid", "my-collector-uuid", "number", "Tank1_Temperature", "Active")
print(json.dumps(new_measurement, indent=2))
```

:::ExpandableHeading
### Successful response

```json
{
  "UUID": "0111a5f4-954e-11f0-ad87-22da883bd9ab",
  "CreatedBy": "6c8ef372-5c29-11ef-9e88-0242ac12000a",
  "CreatedAt": "2025-09-19T11:44:30.637605087Z",
  "UpdatedBy": "6c8ef372-5c29-11ef-9e88-0242ac12000a",
  "UpdatedAt": "2025-09-19T11:44:30.637605087Z",
  "Attributes": null,
  "Metadata": null,
  "OrganizationUUID": "fbf184b2-5c29-11ef-8bf9-0242ac12000a",
  "Name": "tank1.temperature",
  "Description": "",
  "Datatype": "number",
  "Status": "Active",
  "CollectorUUID": "2369d6fe-94bc-11f0-acc7-a25bd411a45c",
  "Collector": {
    "UUID": "2369d6fe-94bc-11f0-acc7-a25bd411a45c",
    "CreatedBy": "6c8ef372-5c29-11ef-9e88-0242ac12000a",
    "CreatedAt": "2025-09-18T18:20:21.736927Z",
    "UpdatedBy": "6c8ef372-5c29-11ef-9e88-0242ac12000a",
    "UpdatedAt": "2025-09-18T18:21:46.542773Z",
    "Attributes": {},
    "Metadata": {},
    "OrganizationUUID": "fbf184b2-5c29-11ef-8bf9-0242ac12000a",
    "Settings": {},
    "Name": "My CSV Collector",
    "CollectorType": "csv",
    "BuildVersion": "5.2.3",
    "BuildOs": "linux",
    "BuildArch": "arm64",
    "Description": "Collector for CSV imports",
    "Status": "Active",
    "MeasurementSettingsSchema": {
      "$schema": "http://json-schema.org/draft-06/schema#",
      "definitions": {},
      "id": "http://factry.io/measurementsettings.json",
      "properties": {
        "Filter": {
          "additionalProperties": false,
          "default": {},
          "description": "Filter to parse only the rows that match the filter. The filter is a JSON object where the key is the column index (as a string) and the value is the value to match. If multiple values in the same column should be matched, separate them with a semicolon.. Use {} to leave empty.",
          "examples": [
            "{\"1\":\"G10391\"}"
          ],
          "id": "/properties/Filter",
          "minProperties": 0,
          "order": 2,
          "patternProperties": {
            "[0-9]+": {
              "type": "string"
            }
          },
          "title": "Filter",
          "type": "object"
        },
        "StatusGood": {
          "description": "All values that are mapped to status 'Good'. Multiple statuses can be configured using semicolon separated values",
          "id": "/properties/StatusGood",
          "order": 3,
          "title": "StatusGood",
          "type": "string"
        },
        "TagsInCSV": {
          "additionalProperties": false,
          "default": {},
          "description": "An optional json configuration to add values from a certain column index (starts from 0) to a tag. Mutiple mappings can be foreseen using one column index and one tag name. Use {} to leave empty.",
          "examples": [
            "{\"1\":\"tagName\"}"
          ],
          "id": "/properties/TagsInCSV",
          "minProperties": 0,
          "order": 5,
          "patternProperties": {
            "[0-9]+": {
              "type": "string"
            }
          },
          "title": "TagsInCSV",
          "type": "object"
        },
        "TimestampLayout": {
          "description": "The layout of the timestamp, default the TimestampLayout setting on the collector will be used. More info: https://pkg.go.dev/time#Layout",
          "id": "/properties/TimestampLayout",
          "order": 4,
          "title": "TimestampLayout",
          "type": "string"
        },
        "ValueColumn": {
          "default": 2,
          "description": "Index of column holding the value (starts from 0)",
          "id": "/properties/ValueColumn",
          "order": 1,
          "title": "ValueColumn",
          "type": "integer"
        }
      },
      "required": [
        "ValueColumn"
      ],
      "type": "object"
    },
    "SettingsSchema": {
      "$id": "http://factry.io/collectorsettings.json",
      "$schema": "http://json-schema.org/draft-06/schema#",
      "definitions": {},
      "properties": {
        "AlternativeTimezone": {
          "$id": "/properties/AlternativeTimezone",
          "description": "This changes the timestamp of points, statistics and logs to the machine local timezone, strips off the timezone and indicates the timezone to be the alternative timezone. The timezone name is taken from the IANA Time Zone database (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).",
          "isAdvanced": true,
          "order": 14,
          "title": "AlternativeTimezone",
          "type": "string"
        },
        "BasePath": {
          "description": "Default directory where the incoming, processed and error directories are in. By default these directory names are respectively, incoming, processed and error. Paths are absolute. Add a trailing forward slash for linux or a trailing backslash for windows",
          "id": "/properties/BasePath",
          "order": 201,
          "title": "BasePath",
          "type": "string"
        },
        "BufferDiskBatches": {
          "$id": "/properties/BufferDiskBatches",
          "default": 100,
          "description": "The maximum amount of batches that will be written to a buffer file.",
          "isAdvanced": true,
          "order": 8,
          "title": "BufferDiskBatches",
          "type": "integer"
        },
        "BufferMaxBatchSize": {
          "$id": "/properties/BufferMaxBatchSize",
          "default": 5000,
          "description": "The maximum size of a batch.",
          "isAdvanced": true,
          "order": 6,
          "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": 7,
          "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": 10,
          "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": 9,
          "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": 5,
          "title": "BufferProcessInterval",
          "type": "integer"
        },
        "CSVHeader": {
          "default": "false",
          "description": "Indicates if there is a header in the csv files.",
          "enum": [
            "true",
            "false"
          ],
          "id": "/properties/CSVHeader",
          "order": 107,
          "title": "CSVHeader",
          "type": "string"
        },
        "CompressionLevel": {
          "$id": "/properties/CompressionLevel",
          "default": -1,
          "description": "The compression level GRPC uses, for default compression. 1-9: 1 = fastest, 9 = most compressed, -1 = default.",
          "isAdvanced": true,
          "maximum": 9,
          "minimum": -1,
          "order": 12,
          "title": "CompressionLevel",
          "type": "integer"
        },
        "Delimiter": {
          "default": ",",
          "description": "The delimiter used in the csv file.",
          "id": "/properties/Delimiter",
          "order": 106,
          "title": "Delimiter",
          "type": "string"
        },
        "ErrorDirectoryPath": {
          "description": "Override directory in which files that contained an error will be put. Invalid CSV files will be stored here",
          "id": "/properties/ErrorDirectoryPath",
          "order": 204,
          "title": "ErrorDirectoryPath",
          "type": "string"
        },
        "FailedMaxAge": {
          "default": 129600,
          "description": "The maximum time in minutes to keep failed files. 0 will keep the files indefinitely",
          "id": "/properties/FailedMaxAge",
          "isAdvanced": true,
          "order": 216,
          "title": "FailedMaxAge",
          "type": "integer"
        },
        "FileMask": {
          "default": "*.csv",
          "description": "File mask of the files to use",
          "id": "/properties/FileMask",
          "order": 205,
          "pattern": "\\*\\.*[a-z]",
          "title": "FileMask",
          "type": "string"
        },
        "GRPCMaxMessageSize": {
          "$id": "/properties/GRPCMaxMessageSize",
          "default": "64MB",
          "description": "The maximum message size for GRPC messages.",
          "isAdvanced": true,
          "order": 13,
          "pattern": "[0-9]+(T|G|M|K)?B",
          "title": "GRPCMaxMessageSize",
          "type": "string"
        },
        "HAPollingInterval": {
          "$id": "/properties/HAPollingInterval",
          "default": 1000,
          "description": "The interval in milliseconds at which the backup collector polls the main collector's health.",
          "isAdvanced": true,
          "order": 11,
          "title": "HAPollingInterval",
          "type": "integer"
        },
        "IncomingDirectoryPath": {
          "description": "Override directory to monitor for files matching FileMask. Paths are absolute",
          "id": "/properties/IncomingDirectoryPath",
          "order": 202,
          "title": "IncomingDirectoryPath",
          "type": "string"
        },
        "LogLevel": {
          "$id": "/properties/LogLevel",
          "default": "info",
          "description": "The log level of the collector.",
          "enum": [
            "trace",
            "debug",
            "info"
          ],
          "isAdvanced": true,
          "order": 1,
          "title": "LogLevel",
          "type": "string"
        },
        "ProcessDelay": {
          "default": 3000,
          "description": "Delay in milliseconds for processing new files after they were detected",
          "id": "/properties/ProcessDelay",
          "isAdvanced": true,
          "order": 213,
          "title": "ProcessDelay",
          "type": "integer"
        },
        "ProcessInterval": {
          "default": 10000,
          "description": "Interval in milliseconds in which the incoming directory is checked for new files",
          "id": "/properties/ProcessInterval",
          "isAdvanced": true,
          "order": 212,
          "title": "ProcessInterval",
          "type": "integer"
        },
        "ProcessedDirectoryPath": {
          "description": "Override directory to which successfully processed files are moved. Paths are absolute",
          "id": "/properties/ProcessedDirectoryPath",
          "order": 203,
          "title": "ProcessedDirectoryPath",
          "type": "string"
        },
        "ProcessedMaxAge": {
          "default": 43200,
          "description": "The maximum time in minutes to keep processed files. 0 will keep the files indefinitely",
          "id": "/properties/ProcessedMaxAge",
          "isAdvanced": true,
          "order": 215,
          "title": "ProcessedMaxAge",
          "type": "integer"
        },
        "SourceTimezone": {
          "$id": "/properties/SourceTimezone",
          "description": "This changes the timestamp of points by stripping off the timezone from the timestamp and indicating the timezone to be the source timezone (f.e. 0h UTC -> 0h UTC+2). Do not use if the points could come from different source devices (f.e. polling vs monitored), since these source devices can have different time settings! The timezone name is taken from the IANA Time Zone database (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).",
          "isAdvanced": true,
          "order": 15,
          "title": "SourceTimezone",
          "type": "string"
        },
        "StartupDelay": {
          "default": 9000,
          "description": "Initial delay for checking the incoming directory in milliseconds",
          "id": "/properties/StartupDelay",
          "isAdvanced": true,
          "order": 214,
          "title": "StartupDelay",
          "type": "integer"
        },
        "StatusColumn": {
          "description": "Index of column holding the status (starts from 0)",
          "id": "/properties/StatusColumn",
          "order": 110,
          "pattern": "[0-9]*",
          "title": "StatusColumn",
          "type": "string"
        },
        "StatusGood": {
          "$id": "/properties/StatusGood",
          "description": "A comma separated list of status strings that will be interpreted as a Good status.",
          "isAdvanced": true,
          "order": 16,
          "title": "StatusGood",
          "type": "string"
        },
        "TickerInterval": {
          "$id": "/properties/TickerInterval",
          "default": 1000,
          "description": "The interval for the base ticker in milliseconds. This ticker is used for the polling of measurements.",
          "isAdvanced": true,
          "minimum": 250,
          "order": 2,
          "title": "TickerInterval",
          "type": "integer"
        },
        "TickerMaxDrift": {
          "$id": "/properties/TickerMaxDrift",
          "default": 125,
          "description": "The maximum drift a tick may have in milliseconds. Must be lower than the interval.",
          "isAdvanced": true,
          "order": 4,
          "title": "TickerMaxDrift",
          "type": "integer"
        },
        "TickerResolution": {
          "$id": "/properties/TickerResolution",
          "default": 25,
          "description": "The resolution for the base ticker in milliseconds. Maximum 1/10th of the the interval.",
          "isAdvanced": true,
          "minimum": 2,
          "order": 3,
          "title": "TickerResolution",
          "type": "integer"
        },
        "TimestampColumn": {
          "default": 1,
          "description": "Index of column holding the timestamp (starts from 0)",
          "id": "/properties/TimestampColumn",
          "order": 108,
          "title": "TimestampColumn",
          "type": "integer"
        },
        "TimestampLayout": {
          "description": "The layout of the timestamp of the measurements, default RFC3339 will be used. More info: https://pkg.go.dev/time#Layout",
          "id": "/properties/TimestampLayout",
          "order": 109,
          "title": "TimestampLayout",
          "type": "string"
        },
        "TrimString": {
          "description": "The string to trim (leading and trailing) from the csv cells used (values, mappings, status, ...)",
          "id": "/properties/TrimString",
          "order": 111,
          "title": "TrimString",
          "type": "string"
        }
      },
      "required": [
        "TimestampColumn",
        "Delimiter",
        "CSVHeader",
        "BasePath",
        "FileMask"
      ],
      "type": "object"
    },
    "State": {},
    "Health": {
      "Health": "Collecting",
      "Timestamp": "2025-09-18T18:21:48.821003Z",
      "CollectorUUID": "2369d6fe-94bc-11f0-acc7-a25bd411a45c"
    },
    "LastSeen": "2025-09-19T11:44:27.04284971Z",
    "IPAddress": "134.209.86.11:34951",
    "HAUUID": null,
    "DefaultDatabaseUUID": null,
    "UpdateCollectorTo": null
  },
  "DatabaseUUID": "19bdd45c-5c2d-11ef-ae29-0242ac12000a",
  "Settings": null,
  "Labels": null
}

```
:::

:::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).
:::

# Update a measurement

This code updates a measurement by providing ([my Swagger](https://historian.mycompany.com:18000/api/swagger/#/measurements/updateMeasurement)):&#x20;

- `DatabaseUUID`: retrieve by [listing the time series databases](docId:64SUMJC8mtVAUv2Wzv13S).
- `CollectorUUID`: retrieve by [listing the collectors](docId\:XyILd8uEb7AS2Mb-qxt3i).
- `Datatype`: e.g. number, boolean, string, ...
- `Name`: Tank1\_Temperature
- `Status`: e.g. Active, Paused ...

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

:::hint{type="info"}
Use the <font color="#6366F1">**PUT** </font>[https://historian.mycompany.com:18000/api/measurements](https://historian.mycompany.com:18000/api/measurements) to create multiple measurements at once too.
:::

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

update_payload = {
    "DatabaseUUID": "my-database-uuid",
    "CollectorUUID": "my-collector-uuid",
    "Datatype": "string",
    "Name": "Tank1_Temperature",
    "Status": "Paused"
}

updated_measurement = update_measurement("my-measurement-uuid", update_payload)
print(json.dumps(updated_measurement, indent=2))
```

:::ExpandableHeading
### Successful response

```json
{
  "UUID": "0111a5f4-954e-11f0-ad87-22da883bd9ab",
  "CreatedBy": null,
  "CreatedAt": "0001-01-01T00:00:00Z",
  "UpdatedBy": "6c8ef372-5c29-11ef-9e88-0242ac12000a",
  "UpdatedAt": "2025-09-19T12:14:36.464632589Z",
  "Attributes": null,
  "Metadata": null,
  "OrganizationUUID": "fbf184b2-5c29-11ef-8bf9-0242ac12000a",
  "Name": "tank1.temperature",
  "Description": "",
  "Datatype": "string",
  "Status": "Active",
  "CollectorUUID": "2369d6fe-94bc-11f0-acc7-a25bd411a45c",
  "DatabaseUUID": "19bdd45c-5c2d-11ef-ae29-0242ac12000a",
  "Settings": null,
  "Labels": null
}

```
:::

# Delete a measurement

This code deletes a measurement given the measurement UUID ([my Swagger](https://historian.mycompany.com:18000/api/swagger/#/measurements/deleteMeasurement)).&#x20;

<font color="#6366F1">**DELETE** </font>[https://historian.mycompany.com:18000/api/measurements/\{measurement\_uuid}](https://historian.mycompany.com:18000/api/measurements/\{measurement_uuid}) (Replace `{measurement_uuid}` with your measurement UUID)

```python
def delete_measurement(measurement_uuid: str):
    resp = session.delete(f"{BASE_URL}/measurements/{measurement_uuid}", timeout=30)
    resp.raise_for_status()
    return resp.json()

delete_measurement("my-measurement-uuid")

```

:::ExpandableHeading
### Successful response

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

