Developer API
The Developer API is the stable integration surface for CO2 platform devices and partner systems. It wraps the internal Supabase tables and RPCs behind versioned HTTP endpoints.
Base URL
Section titled “Base URL”https://data.co2targettracking.co.uk/functions/v1/developer-api/v1Dev:
https://dev.data.co2targettracking.co.uk/functions/v1/developer-api/v1Authentication
Section titled “Authentication”Every request, except health checks, requires an estate-scoped API key.
curl https://data.co2targettracking.co.uk/functions/v1/developer-api/v1/gateways \ -H "X-API-Key: sk_live_your_key_here"Scopes:
| Scope | Allows |
|---|---|
read | List and fetch gateways, sensors, readings, gateway status, and ACLs |
provision | Create or update gateways and sensors, rotate gateway passwords |
ingest | Insert sensor readings |
API keys are hashed in Supabase. Plaintext keys are shown once when created.
Gateways
Section titled “Gateways”GET /gateways
Section titled “GET /gateways”Lists MQTT gateways in the API key estate.
curl "$BASE/gateways?integration=multitech-conduit" \ -H "X-API-Key: $CO2_API_KEY"POST /gateways
Section titled “POST /gateways”Creates an MQTT gateway credential. The returned password is shown once.
Required scope: provision
curl -X POST "$BASE/gateways" \ -H "Content-Type: application/json" \ -H "X-API-Key: $CO2_API_KEY" \ -d '{ "integration": "multitech-conduit", "username": "gw_north_roof", "metadata": { "firmware": "mpower-6", "region": "EU868", "gateway_eui": "00800000a0001234", "site": "North roof" } }'Response:
{ "status": "created", "gateway": { "id": "uuid", "estate_id": "estate-id", "integration": "multitech-conduit", "username": "gw_north_roof", "client_id": "gw_north_roof", "disabled": false, "metadata": {} }, "credentials": { "username": "gw_north_roof", "client_id": "gw_north_roof", "password": "shown-once", "broker": { "host": "mqtt.co2targettracking.co.uk", "port_tls": 8883 } }}GET /gateways/:id
Section titled “GET /gateways/:id”Fetches one gateway.
PATCH /gateways/:id
Section titled “PATCH /gateways/:id”Updates mutable gateway fields.
Required scope: provision
{ "disabled": true, "metadata": { "site": "North roof - cabinet 2" }}Metadata is merged into the existing metadata object.
POST /gateways/:id/rotate-password
Section titled “POST /gateways/:id/rotate-password”Rotates the gateway password and returns the new plaintext once.
Required scope: provision
GET /gateways/:id/status
Section titled “GET /gateways/:id/status”Returns the live EMQX connection probe when broker management credentials are configured. Otherwise it returns connected: null plus last_seen_at.
GET /gateways/:id/acl
Section titled “GET /gateways/:id/acl”Returns the broker ACL rules seeded for that gateway.
Sensors
Section titled “Sensors”GET /sensors
Section titled “GET /sensors”Lists sensors in the API key estate. Query parameters: asset_id, sensor_type, is_active, limit.
POST /sensors
Section titled “POST /sensors”Creates a sensor.
Required scope: provision
curl -X POST "$BASE/sensors" \ -H "Content-Type: application/json" \ -H "X-API-Key: $CO2_API_KEY" \ -d '{ "asset_id": "asset-id", "site_id": "site-id", "sensor_type": "water_level", "name": "Tank A level", "unit": "litres", "metadata": { "model": "FMU30" } }'GET /sensors/:id
Section titled “GET /sensors/:id”Fetches one sensor.
PATCH /sensors/:id
Section titled “PATCH /sensors/:id”Updates name, unit, is_active, or metadata.
Required scope: provision
Readings
Section titled “Readings”GET /readings
Section titled “GET /readings”Lists readings for the API key estate. Query parameters: sensor_id, from, to, limit.
Required scope: read
POST /readings
Section titled “POST /readings”Inserts one or more readings.
Required scope: ingest
curl -X POST "$BASE/readings" \ -H "Content-Type: application/json" \ -H "X-API-Key: $CO2_API_KEY" \ -d '{ "sensor_id": "sensor-uuid", "value": 42.5, "recorded_at": "2026-04-27T14:00:00Z", "metadata": { "battery_pct": 72 } }'Batch mode accepts up to 100 readings:
{ "readings": [ { "sensor_id": "sensor-uuid", "value": 42.5 }, { "sensor_id": "sensor-uuid", "value": 43.1 } ]}Duplicate readings with the same sensor_id and recorded_at are upserted.