Enterprise API¶
ChillCheck provides a read-only REST API for Enterprise plan customers. Use it to pull temperature data, alerts, and audit logs into your own BI tools, food safety management systems, or spreadsheet integrations.
Enterprise plan required
API access is only available on the Enterprise plan. Contact hello@chillcheck.online to upgrade.
Authentication¶
All API requests must include an API key in the Authorization header:
Generate and manage API keys in Settings → API. Keys are organisation-scoped — a single key provides read access to all sites and cabinets within your organisation.
Keep your key secret
API keys grant read access to all your monitoring data. Treat them like passwords. The full key is only shown once at generation — store it somewhere secure (a password manager or secrets manager). If a key is compromised, revoke it immediately and generate a replacement.
Base URL¶
Response format¶
All endpoints return a JSON object with data and meta:
| Field | Description |
|---|---|
data |
Array of resource objects |
meta.count |
Total matching rows (across all pages) |
meta.limit |
Page size used |
meta.page |
Current page number |
meta.has_more |
true if more pages exist |
Pagination¶
Use ?limit=N&page=N to paginate:
- Default limit: 1,000 rows
- Maximum limit: 10,000 rows per request
- Pages are 1-indexed
Error responses¶
| Status | Meaning |
|---|---|
401 |
Missing, invalid, or revoked API key |
403 |
Organisation is not on an Enterprise plan |
500 |
Internal error — contact support if persistent |
Endpoints¶
GET /api/v1/sites¶
List all sites in your organisation.
Query parameters: none
Example response:
{
"data": [
{
"id": "uuid",
"name": "Riverside Kitchen",
"address": "12 Broad Street, Bristol",
"postcode": "BS1 2EP",
"timezone": "Europe/London",
"created_at": "2026-01-15T09:00:00Z",
"updated_at": "2026-01-15T09:00:00Z"
}
],
"meta": { "count": 3 }
}
GET /api/v1/cabinets¶
List active cabinets, optionally filtered by site.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
site_id |
UUID | Filter to a specific site |
Example response:
{
"data": [
{
"id": "uuid",
"site_id": "uuid",
"name": "Walk-in Fridge",
"type": "fridge",
"location": "Main kitchen",
"target_temp": 4,
"warn_low": 1,
"warn_high": 6,
"crit_low": -1,
"crit_high": 8,
"notes": "Serves prep and cold storage",
"active": true,
"alerts_muted_until": null,
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-04-20T14:00:00Z"
}
],
"meta": { "count": 5 }
}
GET /api/v1/readings¶
Temperature readings, newest first. Default 1,000 rows per page.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
cabinet_id |
UUID | Filter to a specific cabinet |
site_id |
UUID | Filter to a specific site |
from |
ISO 8601 | Start of time range (inclusive), e.g. 2026-05-01T00:00:00Z |
to |
ISO 8601 | End of time range (inclusive) |
source |
sensor | manual |
Filter by reading source |
limit |
integer | Rows per page (max 10,000) |
page |
integer | Page number (1-indexed) |
Example:
Example response:
{
"data": [
{
"id": "uuid",
"cabinet_id": "uuid",
"site_id": "uuid",
"sensor_id": "uuid",
"temperature": 4.2,
"recorded_at": "2026-05-31T14:32:00Z",
"synced_at": "2026-05-31T14:32:05Z",
"source": "sensor",
"method": null,
"notes": null
}
],
"meta": {
"count": 44640,
"limit": 1000,
"page": 1,
"has_more": true
}
}
Fetching all readings for a time range
For large exports, loop through pages until has_more is false:
GET /api/v1/alerts¶
Alerts (temperature breaches, sensor/device offline), newest first.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
cabinet_id |
UUID | Filter to a specific cabinet |
site_id |
UUID | Filter to a specific site |
status |
open | resolved | all |
Default all |
severity |
warning | critical |
Filter by severity |
from |
ISO 8601 | Filter by triggered_at ≥ this value |
to |
ISO 8601 | Filter by triggered_at ≤ this value |
limit |
integer | Rows per page (max 10,000) |
page |
integer | Page number (1-indexed) |
Example response:
{
"data": [
{
"id": "uuid",
"cabinet_id": "uuid",
"site_id": "uuid",
"sensor_id": "uuid",
"type": "high_temp",
"severity": "critical",
"temperature": 9.4,
"message": "Walk-in Fridge reached 9.4°C (critical high: 8°C)",
"triggered_at": "2026-05-30T22:14:00Z",
"resolved_at": "2026-05-30T22:52:00Z",
"acknowledged_at": "2026-05-30T22:18:00Z",
"acknowledged_by": "Jane Smith",
"root_cause": "door_left_open",
"acknowledgment_note": "Found door ajar after delivery",
"escalation_level": 1
}
],
"meta": { "count": 14, "limit": 1000, "page": 1, "has_more": false }
}
Alert types:
| Type | Description |
|---|---|
high_temp |
Temperature above critical or warning high threshold |
low_temp |
Temperature below critical or warning low threshold |
sensor_offline |
Sensor not reporting |
device_offline |
Hub not reporting |
low_battery |
Sensor battery below threshold |
low_signal |
Sensor signal below threshold |
predictive_drift |
Temperature trending towards a breach (predictive, Pi-side) |
GET /api/v1/audit¶
Immutable audit log of all user and system events, newest first. Useful for compliance reporting.
Query parameters:
| Parameter | Type | Description |
|---|---|---|
action |
string | Filter by action prefix, e.g. alert. or cabinet. |
from |
ISO 8601 | Start of time range |
to |
ISO 8601 | End of time range |
limit |
integer | Rows per page (max 5,000) |
page |
integer | Page number (1-indexed) |
Example:
Example response:
{
"data": [
{
"id": "uuid",
"profile_id": "uuid",
"action": "alert.acknowledged",
"metadata": {
"alert_id": "uuid",
"cabinet_name": "Walk-in Fridge",
"root_cause": "door_left_open"
},
"created_at": "2026-05-30T22:18:00Z"
}
],
"meta": { "count": 312, "limit": 500, "page": 1, "has_more": true }
}
Common audit actions include alert.raised, alert.resolved, alert.acknowledged, cabinet.created, cabinet.updated, sensor.assigned, user.invited, api_key.created, api_key.revoked, and more.
Code examples¶
Python (requests)¶
import requests
BASE = "https://app.chillcheck.online/api/v1"
HEADERS = {"Authorization": "Bearer cc_live_your_key_here"}
# List sites
sites = requests.get(f"{BASE}/sites", headers=HEADERS).json()
# Fetch readings for a cabinet, last 7 days
from datetime import datetime, timedelta, timezone
from_ts = (datetime.now(timezone.utc) - timedelta(days=7)).isoformat()
readings = requests.get(
f"{BASE}/readings",
params={"cabinet_id": "your-cabinet-uuid", "from": from_ts, "limit": 10000},
headers=HEADERS,
).json()
print(f"Fetched {readings['meta']['count']} readings")
curl¶
API_KEY="cc_live_your_key_here"
BASE="https://app.chillcheck.online/api/v1"
# List sites
curl -H "Authorization: Bearer $API_KEY" "$BASE/sites"
# Open alerts for a site
curl -H "Authorization: Bearer $API_KEY" \
"$BASE/alerts?site_id=your-site-uuid&status=open"
# Readings for a date range
curl -H "Authorization: Bearer $API_KEY" \
"$BASE/readings?cabinet_id=your-cabinet-uuid&from=2026-05-01T00:00:00Z&to=2026-05-31T23:59:59Z"
Google Sheets (importdata workaround)¶
For simple use cases, you can proxy the API via a small script or use Apps Script to import data directly into a Google Sheet using the UrlFetchApp service.
Managing API keys¶
API keys are managed in Settings → API (Enterprise plan accounts only).
- Generate a new key — Enter a descriptive name (e.g. "BI dashboard", "Zapier"). The full key is shown once — copy it immediately.
- Revoke a key — Click Revoke next to any key. Revocation is immediate; any integration using the key will receive
401responses. - Keys do not expire automatically. Create a rotation policy appropriate for your security requirements.
Only organisation owners can generate and revoke keys. Admins and members can view the key list (prefixes only — not the full key).