> ## Documentation index
> Fetch the complete documentation index at: https://developer.rhombus.com/llms.txt
> Use it 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](https://console.rhombussystems.com/settings/integrations/api-tokens/) under **Settings → Integrations & Developer Resources → API Tokens**)
> - At least one **E-series environmental sensor** deployed and connected to an environmental gateway
> - A **configured location** where your sensors are installed

## 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.

```python Python
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
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
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 '{}'
```

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`.

## 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.

```python Python
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
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
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
  }'
```

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.

## Configure sensors

### Get sensor configuration

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

```python Python
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
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
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"
  }'
```

### 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.

```python Python
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
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
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
  }'
```

> **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.

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

```python Python
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
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
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
            }
          ]
        }
      ]
    }
  }'
```

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

### List climate policies

Retrieve all climate policies configured for your organization.

```python Python
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
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
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 '{}'
```

## 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.

```python Python
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
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
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 '{}'
```

### Get gateway events

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

```python Python
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
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
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
  }'
```

## 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.

```python Python
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
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
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
```

> **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.

You can also export environmental gateway events with the same pattern using [`/api/export/environmentalGatewayEvents`](https://developer.rhombus.com/api-reference/export-webservice/download-environmental-gateway-event-log).

## Next steps

- **[Alarm Monitoring](https://developer.rhombus.com/implementations/alarm-monitoring)**: Set up automated alert responses when sensor thresholds trigger alarms
- **[Webhook Notifications](https://developer.rhombus.com/webhooks)**: Receive real-time push notifications when sensor readings cross thresholds
