HTTPS JSON on the same origin as the portal, paths under /v1. Authorization: Bearer <api_key> (pcv_…), scope read. Errors may set X-Request-ID (= error.request_id). Older keys may use read:pumps / read:stats only.
error.code: rate_limited, and Retry-After (seconds until the window resets).Root-relative URLs. Access = pumps visible to portal users bound to your integration. JSON may omit undefined keys.
GET /v1/pumpsQuery page, limit. Paginated controllers; statistics is fleet-wide for the integration.
/v1/pumps?page=1&limit=50
{
"api_version": "1",
"controllers": [
{
"pump_id": "pump-001",
"custom_name": "North field",
"is_owner": 1,
"last_seen": "2025-03-20T10:00:00.000Z",
"last_heartbeat": "2025-03-20T10:00:00.000Z",
"installation": { "installation_name": "Main", "location_name": "Site A", "lat": 52.0, "lon": 5.0 },
"pump": { "status": "running", "total_water_delivered": 15420.5, "running": true },
"battery": { "voltage": 12.6, "soc": 85, "current": -2.3 },
"communication_method": "MQTT",
"current_pressure": 4.2,
"active_alarms_count": 0,
"highest_alarm_level": null,
"total_sessions": 12,
"uptime": 86400,
"profile": "IRRIGATION"
}
],
"statistics": {
"total_controllers": 1,
"active_controllers": 1,
"offline_controllers": 0,
"total_water_delivered": 15420.5,
"average_battery_soc": 85,
"wireguard_connections": 0
},
"pagination": {
"page": 1,
"limit": 50,
"total": 1,
"pages": 1,
"has_next": false,
"has_prev": false
}
}
GET /v1/statsstatistics only (same object as GET /v1/pumps).
/v1/stats
{
"api_version": "1",
"statistics": {
"total_controllers": 12,
"active_controllers": 10,
"offline_controllers": 2,
"total_water_delivered": 15420.5,
"average_battery_soc": 82.5,
"wireguard_connections": 3
}
}
GET /v1/delegated-usersOne row per delegated user (aggregates for that user’s pumps only). Each row includes user_id and portal display name (may be null). Email is never returned.
/v1/delegated-users
{
"api_version": "1",
"user_identity_policy": "user_id_and_name",
"delegated_users": [
{
"user_id": 101,
"name": "Acme Farms",
"total_controllers": 3,
"active_controllers": 2,
"offline_controllers": 1,
"total_water_delivered": 4200.0,
"average_battery_soc": 78.3,
"wireguard_connections": 1
}
]
}
GET /v1/users/:userId/summaryPer delegated user: same statistics and paginated controllers shape as GET /v1/pumps, but only that user’s pumps (page, limit). This is not the time-series payload of GET /v1/pumps/:pumpId/summary.
/v1/users/101/summary?page=1&limit=50
{
"api_version": "1",
"user_id": 101,
"name": "Acme Farms",
"statistics": {
"total_controllers": 1,
"active_controllers": 1,
"offline_controllers": 0,
"total_water_delivered": 15420.5,
"average_battery_soc": 85,
"wireguard_connections": 0
},
"controllers": [
{ "pump_id": "pump-001", "custom_name": "North field", "is_owner": 1 }
],
"pagination": {
"page": 1,
"limit": 50,
"total": 1,
"pages": 1,
"has_next": false,
"has_prev": false
}
}
GET /v1/pumps/:pumpId/metadataPersisted controller metadata.
/v1/pumps/PUMP_ID/metadata
{
"api_version": "1",
"pump_id": "pump-001",
"metadata": {
"pump_id": "pump-001",
"installation_name": "Main",
"location_name": "Site A",
"latitude": 52.0,
"longitude": 5.0,
"last_seen": "2025-03-20T10:00:00.000Z",
"total_water_delivered": 15420.5
}
}
More metadata fields may appear over time.
GET /v1/pumps/:pumpId/summaryLive fields, today, alarms, week trends, lifetime aggregates.
/v1/pumps/PUMP_ID/summary
{
"api_version": "1",
"pump_id": "pump-001",
"metadata": { "pump_id": "pump-001" },
"live_data": { "current_pressure": null, "battery_soc": 84, "battery_voltage": 12.5, "last_updated": "…" },
"today": { "date": "2025-03-20", "statistics": { }, "snapshot_count": 0, "is_today": true },
"recent_alarms": { "count": 0, "critical": 0, "warning": 0, "alarms": [] },
"week_trends": { "daily_summaries": [], "total_water_delivered": "0.0", "avg_pressure": null, "avg_battery_soc": null, "avg_uptime": "0" },
"total_average_water": { "avg_daily_water": 0, "total_water": 0, "days_with_data": 0, "calculation_method": "no_data" },
"lifetime_averages": { "avg_pressure": null, "avg_battery_soc": null, "calculation_method": "no_data" },
"last_updated": "2025-03-20T10:00:00.000Z",
"data_source": "database"
}
Body shape:
{
"error": {
"code": "invalid_api_key",
"message": "Human-readable detail",
"request_id": "…"
}
}
| HTTP | error.code | Typical cause |
|---|---|---|
| 400 | invalid_pagination | Bad page / limit on GET /v1/pumps or GET /v1/users/:userId/summary. |
| 400 | invalid_user_id | Non-numeric userId in GET /v1/users/:userId/summary. |
| 401 | unauthorized | Missing or bad Bearer token. |
| 401 | invalid_api_key | Unknown or revoked key. |
| 403 | no_delegated_users | No portal users on this integration. |
| 403 | insufficient_scope | Key lacks read scope. |
| 403 | forbidden | No access to that pumpId, or userId is not a delegated user on this integration (or inactive). |
| 404 | not_found | No metadata/summary for that pump. |
| 429 | rate_limited | Too many requests; see Retry-After. |
| 500 | internal_error | Auth lookup failed. |