> ## Documentation Index
> Fetch the complete documentation index at: https://api-docs.rhombus.community/llms.txt
> Use this file to discover all available pages before exploring further.

# IoT Sensors

> Read climate data from Rhombus IoT sensors via the API to monitor temperature, humidity, air quality, and environmental conditions across your facilities.

## Overview

Rhombus IoT sensors (E-series) continuously monitor environmental conditions across your facilities. These sensors capture temperature, humidity, indoor air quality (IAQ), CO2 levels, TVOC, and PM2.5, reporting data through environmental gateways back to the Rhombus platform.

Through the API, you can:

* **List sensors** and retrieve their current readings
* **Query historical data** for trend analysis and reporting
* **Configure sensors** by updating descriptions, locations, and camera associations
* **Set up climate alert policies** that trigger when readings cross defined thresholds
* **Monitor gateways** that relay data from sensors to the cloud
* **Export data** as CSV for external analysis tools

## Prerequisites

<Note>
  Before you begin, make sure you have:

  * A **Rhombus API key** with sensor permissions (generated in the Rhombus Console under Settings > API)
  * At least one **E-series environmental sensor** deployed and connected to an environmental gateway
  * A **configured location** where your sensors are installed
</Note>

## List All Sensors

Retrieve the current state of every climate sensor in your organization. This returns each sensor's UUID, name, current readings, battery level, and health status.

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api2.rhombussystems.com/api/climate/getMinimalClimateStateList",
      headers=headers,
      json={}
  )

  data = response.json()
  for sensor in data.get("climateStates", []):
      name = sensor.get("name", "Unnamed")
      temp_c = sensor.get("temperatureCelcius")
      humidity = sensor.get("humidity")
      iaq = sensor.get("iaq")
      battery = sensor.get("batteryPercent")
      temp_f = round(temp_c * 9 / 5 + 32, 1) if temp_c else None
      print(f"{name}: {temp_f}°F, {humidity}% RH, IAQ {iaq}, Battery {battery}%")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api2.rhombussystems.com/api/climate/getMinimalClimateStateList', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({})
  });

  const data = await response.json();
  for (const sensor of data.climateStates || []) {
    const tempF = sensor.temperatureCelcius
      ? (sensor.temperatureCelcius * 9 / 5 + 32).toFixed(1)
      : null;
    console.log(`${sensor.name}: ${tempF}°F, ${sensor.humidity}% RH, IAQ ${sensor.iaq}, Battery ${sensor.batteryPercent}%`);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/climate/getMinimalClimateStateList \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{}'
  ```
</CodeGroup>

The response includes a `climateStates` array. Key fields for each sensor:

| Field                | Type    | Description                               |
| -------------------- | ------- | ----------------------------------------- |
| `sensorUuid`         | string  | Unique identifier for the sensor          |
| `name`               | string  | Display name (e.g., "Server Room Sensor") |
| `temperatureCelcius` | float   | Current temperature in Celsius            |
| `humidity`           | float   | Relative humidity percentage              |
| `iaq`                | float   | Indoor Air Quality index                  |
| `co2`                | float   | CO2 level in ppm                          |
| `tvoc`               | float   | Total Volatile Organic Compounds          |
| `pm25`               | float   | PM2.5 particulate matter                  |
| `batteryPercent`     | integer | Battery level (0-100)                     |
| `health`             | string  | Sensor health status (`GREEN` or `RED`)   |
| `locationUuid`       | string  | Location where the sensor is assigned     |

<Tip>
  Temperature is returned in Celsius. To convert to Fahrenheit: `°F = °C × 9/5 + 32`.
</Tip>

## Read Sensor Data

Query historical climate events for a specific sensor over a time range. Each event represents a data point with temperature, humidity, air quality, and other environmental readings.

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  # Query the last 24 hours of data
  now_ms = int(time.time() * 1000)
  one_day_ago_ms = now_ms - (24 * 60 * 60 * 1000)

  response = requests.post(
      "https://api2.rhombussystems.com/api/climate/getClimateEventsForSensor",
      headers=headers,
      json={
          "sensorUuid": "YOUR_SENSOR_UUID",
          "createdAfterMs": one_day_ago_ms,
          "createdBeforeMs": now_ms,
          "limit": 100
      }
  )

  data = response.json()
  for event in data.get("climateEvents", []):
      temp_c = event.get("temp")
      humidity = event.get("humidity")
      timestamp = event.get("timestampMs")
      temp_f = round(temp_c * 9 / 5 + 32, 1) if temp_c else None
      print(f"[{timestamp}] {temp_f}°F, {humidity}% RH")
  ```

  ```javascript JavaScript theme={null}
  const now = Date.now();
  const oneDayAgo = now - (24 * 60 * 60 * 1000);

  const response = await fetch('https://api2.rhombussystems.com/api/climate/getClimateEventsForSensor', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      sensorUuid: 'YOUR_SENSOR_UUID',
      createdAfterMs: oneDayAgo,
      createdBeforeMs: now,
      limit: 100
    })
  });

  const data = await response.json();
  for (const event of data.climateEvents || []) {
    const tempF = event.temp ? (event.temp * 9 / 5 + 32).toFixed(1) : null;
    console.log(`[${new Date(event.timestampMs).toISOString()}] ${tempF}°F, ${event.humidity}% RH`);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/climate/getClimateEventsForSensor \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "sensorUuid": "YOUR_SENSOR_UUID",
      "createdAfterMs": 1712620800000,
      "createdBeforeMs": 1712707200000,
      "limit": 100
    }'
  ```
</CodeGroup>

Each climate event includes these fields:

| Field           | Type    | Description                            |
| --------------- | ------- | -------------------------------------- |
| `timestampMs`   | integer | Event timestamp in epoch milliseconds  |
| `temp`          | float   | Temperature in Celsius at this reading |
| `humidity`      | float   | Relative humidity percentage           |
| `iaq`           | float   | Indoor Air Quality index               |
| `co2`           | float   | CO2 concentration                      |
| `tvoc`          | float   | Total Volatile Organic Compounds       |
| `pm25`          | float   | PM2.5 particulate matter               |
| `heatIndexDegF` | float   | Calculated heat index in Fahrenheit    |

<Note>
  The `limit` parameter caps the number of events returned. If you need more data points than the limit allows, paginate by adjusting the `createdAfterMs` and `createdBeforeMs` window.
</Note>

## Configure Sensors

### Get Sensor Configuration

Retrieve the full configuration for a specific sensor, including its threshold settings and associated devices.

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api2.rhombussystems.com/api/climate/getConfig",
      headers=headers,
      json={
          "uuid": "YOUR_SENSOR_UUID"
      }
  )

  config = response.json().get("config", {})
  print(config)
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api2.rhombussystems.com/api/climate/getConfig', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      uuid: 'YOUR_SENSOR_UUID'
    })
  });

  const data = await response.json();
  console.log(data.config);
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/climate/getConfig \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "uuid": "YOUR_SENSOR_UUID"
    }'
  ```
</CodeGroup>

### Update Sensor Details

Update a sensor's description, location assignment, or camera associations. Fields you include with their corresponding `*Updated` flag set to `true` will be modified; all others remain unchanged.

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api2.rhombussystems.com/api/climate/updateDetails",
      headers=headers,
      json={
          "uuid": "YOUR_SENSOR_UUID",
          "description": "Server Room B - Rack 4 temperature and humidity monitor",
          "descriptionUpdated": True,
          "locationUuid": "YOUR_LOCATION_UUID",
          "locationUuidUpdated": True
      }
  )

  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api2.rhombussystems.com/api/climate/updateDetails', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      uuid: 'YOUR_SENSOR_UUID',
      description: 'Server Room B - Rack 4 temperature and humidity monitor',
      descriptionUpdated: true,
      locationUuid: 'YOUR_LOCATION_UUID',
      locationUuidUpdated: true
    })
  });

  const data = await response.json();
  console.log(data);
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/climate/updateDetails \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "uuid": "YOUR_SENSOR_UUID",
      "description": "Server Room B - Rack 4 temperature and humidity monitor",
      "descriptionUpdated": true,
      "locationUuid": "YOUR_LOCATION_UUID",
      "locationUuidUpdated": true
    }'
  ```
</CodeGroup>

<Warning>
  You must set the corresponding `*Updated` flag to `true` for each field you want to change. For example, setting `description` without `descriptionUpdated: true` will have no effect.
</Warning>

## Set Up Climate Alerts

Climate policies define threshold rules that trigger alerts when environmental readings go above or below specified values. Create a policy and associate it with sensors to receive notifications.

### Create a Climate Policy

This example creates a policy that alerts when temperature exceeds 80°F (26.7°C) or drops below 40°F (4.4°C).

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api2.rhombussystems.com/api/policy/createClimatePolicy",
      headers=headers,
      json={
          "policy": {
              "name": "Server Room Temperature Alert",
              "description": "Alert when server room temperature is outside safe operating range",
              "scheduledTriggers": [
                  {
                      "triggerSet": [
                          {
                              "activity": "TEMPERATURE_EXCEEDED_HIGH",
                              "threshold": 26.7
                          },
                          {
                              "activity": "TEMPERATURE_EXCEEDED_LOW",
                              "threshold": 4.4
                          },
                          {
                              "activity": "HUMIDITY_EXCEEDED_HIGH",
                              "threshold": 60.0
                          }
                      ]
                  }
              ]
          }
      }
  )

  data = response.json()
  print(f"Created policy: {data.get('policyUuid')}")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api2.rhombussystems.com/api/policy/createClimatePolicy', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      policy: {
        name: 'Server Room Temperature Alert',
        description: 'Alert when server room temperature is outside safe operating range',
        scheduledTriggers: [
          {
            triggerSet: [
              {
                activity: 'TEMPERATURE_EXCEEDED_HIGH',
                threshold: 26.7
              },
              {
                activity: 'TEMPERATURE_EXCEEDED_LOW',
                threshold: 4.4
              },
              {
                activity: 'HUMIDITY_EXCEEDED_HIGH',
                threshold: 60.0
              }
            ]
          }
        ]
      }
    })
  });

  const data = await response.json();
  console.log(`Created policy: ${data.policyUuid}`);
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/policy/createClimatePolicy \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "policy": {
        "name": "Server Room Temperature Alert",
        "description": "Alert when server room temperature is outside safe operating range",
        "scheduledTriggers": [
          {
            "triggerSet": [
              {
                "activity": "TEMPERATURE_EXCEEDED_HIGH",
                "threshold": 26.7
              },
              {
                "activity": "TEMPERATURE_EXCEEDED_LOW",
                "threshold": 4.4
              },
              {
                "activity": "HUMIDITY_EXCEEDED_HIGH",
                "threshold": 60.0
              }
            ]
          }
        ]
      }
    }'
  ```
</CodeGroup>

<Tip>
  Threshold values for temperature triggers use Celsius. Convert your target Fahrenheit values before creating the policy: `°C = (°F - 32) × 5/9`.
</Tip>

### List Climate Policies

Retrieve all climate policies configured for your organization.

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api2.rhombussystems.com/api/policy/getClimatePolicies",
      headers=headers,
      json={}
  )

  data = response.json()
  for policy in data.get("policies", []):
      print(f"{policy.get('name')}: {policy.get('uuid')}")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api2.rhombussystems.com/api/policy/getClimatePolicies', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({})
  });

  const data = await response.json();
  for (const policy of data.policies || []) {
    console.log(`${policy.name}: ${policy.uuid}`);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/policy/getClimatePolicies \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{}'
  ```
</CodeGroup>

## Environmental Gateways

Environmental gateways are the hardware hubs that receive data from nearby E-series sensors via Bluetooth and relay it to the Rhombus cloud. Each gateway supports multiple sensors and connects over your network.

Use the gateway status endpoint to check connectivity, firmware versions, and which sensors each gateway is serving.

<CodeGroup>
  ```python Python theme={null}
  import requests

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  response = requests.post(
      "https://api2.rhombussystems.com/api/climate/getMinimalEnvironmentalGatewayStates",
      headers=headers,
      json={}
  )

  data = response.json()
  for gw in data.get("minimalEnvironmentalGatewayStates", []):
      print(f"Gateway: {gw.get('name')} ({gw.get('deviceUuid')})")
      print(f"  Health: {gw.get('healthStatus')}, Firmware: {gw.get('firmwareVersion')}")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api2.rhombussystems.com/api/climate/getMinimalEnvironmentalGatewayStates', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({})
  });

  const data = await response.json();
  for (const gw of data.minimalEnvironmentalGatewayStates || []) {
    console.log(`Gateway: ${gw.name} (${gw.deviceUuid})`);
    console.log(`  Health: ${gw.healthStatus}, Firmware: ${gw.firmwareVersion}`);
  }
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/climate/getMinimalEnvironmentalGatewayStates \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{}'
  ```
</CodeGroup>

### Get Gateway Events

Query historical events for a specific gateway, such as connectivity changes and sensor registration.

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  now_ms = int(time.time() * 1000)
  one_week_ago_ms = now_ms - (7 * 24 * 60 * 60 * 1000)

  response = requests.post(
      "https://api2.rhombussystems.com/api/climate/getEventsForEnvironmentalGateway",
      headers=headers,
      json={
          "deviceUuid": "YOUR_GATEWAY_UUID",
          "createdAfterMs": one_week_ago_ms,
          "createdBeforeMs": now_ms
      }
  )

  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const now = Date.now();
  const oneWeekAgo = now - (7 * 24 * 60 * 60 * 1000);

  const response = await fetch('https://api2.rhombussystems.com/api/climate/getEventsForEnvironmentalGateway', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      deviceUuid: 'YOUR_GATEWAY_UUID',
      createdAfterMs: oneWeekAgo,
      createdBeforeMs: now
    })
  });

  const data = await response.json();
  console.log(data);
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/climate/getEventsForEnvironmentalGateway \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "deviceUuid": "YOUR_GATEWAY_UUID",
      "createdAfterMs": 1712016000000,
      "createdBeforeMs": 1712620800000
    }'
  ```
</CodeGroup>

## Export Sensor Data

Export climate sensor data as a CSV file for use in spreadsheets, data analysis tools, or compliance reporting. Specify a sensor and time range to download all recorded readings.

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  headers = {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  # Export the last 30 days of data
  now_ms = int(time.time() * 1000)
  thirty_days_ago_ms = now_ms - (30 * 24 * 60 * 60 * 1000)

  response = requests.post(
      "https://api2.rhombussystems.com/api/export/climateEvents",
      headers=headers,
      json={
          "sensorUuid": "YOUR_SENSOR_UUID",
          "createdAfterMs": thirty_days_ago_ms,
          "createdBeforeMs": now_ms
      }
  )

  # Response is CSV data
  with open("climate_export.csv", "w") as f:
      f.write(response.text)
  print("Exported climate data to climate_export.csv")
  ```

  ```javascript JavaScript theme={null}
  const now = Date.now();
  const thirtyDaysAgo = now - (30 * 24 * 60 * 60 * 1000);

  const response = await fetch('https://api2.rhombussystems.com/api/export/climateEvents', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-auth-scheme': 'api-token',
      'x-auth-apikey': 'YOUR_API_KEY'
    },
    body: JSON.stringify({
      sensorUuid: 'YOUR_SENSOR_UUID',
      createdAfterMs: thirtyDaysAgo,
      createdBeforeMs: now
    })
  });

  // Response is CSV text
  const csvData = await response.text();
  console.log(csvData);
  ```

  ```bash cURL theme={null}
  curl -X POST https://api2.rhombussystems.com/api/export/climateEvents \
    -H "Content-Type: application/json" \
    -H "x-auth-scheme: api-token" \
    -H "x-auth-apikey: YOUR_API_KEY" \
    -d '{
      "sensorUuid": "YOUR_SENSOR_UUID",
      "createdAfterMs": 1710028800000,
      "createdBeforeMs": 1712620800000
    }' \
    -o climate_export.csv
  ```
</CodeGroup>

<Note>
  The export endpoint returns CSV data directly in the response body, not JSON. Use the `-o` flag in cURL or write the response text to a file in your application.
</Note>

You can also export environmental gateway events with the same pattern using `/api/export/environmentalGatewayEvents`.

## Next Steps

<CardGroup cols={2}>
  <Card title="Alarm Monitoring" icon="bell" href="/implementations/alarm-monitoring">
    Set up automated alert responses when sensor thresholds trigger alarms
  </Card>

  <Card title="Webhook Notifications" icon="webhook" href="/webhooks">
    Receive real-time push notifications when sensor readings cross thresholds
  </Card>
</CardGroup>
