AquaGen API Reference
This document covers every AquaGen platform API that the new AI agents will call. These are the actual production endpoints — not placeholder paths. Every agent must go through the authenticated API client and never call endpoints outside its assigned domain.
Authentication
Base URL: https://prod-aquagen.azurewebsites.net
All requests require a Bearer token from the login response.
Authorization: Bearer {accessToken}
Login
GET /api/user/user/login
Headers:
username: user@example.com
password: xxxxxxxx
LoginType: WEB
Params:
format: v1
Response:
{
"token": "Bearer eyJ...",
"refreshToken": "eyJ...",
"userId": "abc123",
"username": "user@example.com",
"context": {
"industry": {
"industryId": "ind_001",
"industryName": "AquaTech Ltd",
"startDate": "01/06/2023",
"timezone": "Asia/Kolkata"
},
"services": [
{ "standardCategoryId": "SOURCE_CATEGORY", "displayName": "Source" },
{ "standardCategoryId": "ENERGY_CATEGORY", "displayName": "Energy" }
],
"reportsTab": [
{ "id": "SOURCE_CATEGORY" },
{ "id": "ENERGY_CATEGORY" }
]
}
}
Token Refresh
POST /api/user/refreshToken
Body: { "refreshToken": "eyJ..." }
Token lifespan is 4 hours. Refresh proactively when within 5 minutes of expiry.
Service Categories
Each customer has a subset of these enabled based on their subscription:
| Category ID | What It Covers |
|---|---|
SOURCE_CATEGORY | Water flow meters (sources + consumption points) |
ENERGY_CATEGORY | Energy meters |
STOCK_CATEGORY | Storage tanks (sumps, overhead tanks, reservoirs) |
GROUND_WATER_LEVEL | Groundwater level sensors (water table depth) |
QUALITY_CATEGORY | Water quality sensors (pH, TDS, COD, BOD, etc.) |
RAIN_WATER_CATEGORY | Rain gauges |
VIRTUAL_CATEGORY | Calculated/derived virtual meters — never count as devices |
Core Data API
GET /api/user/deviceDataV2 — Primary data endpoint
Used by: Dashboard, Water Flow, Water Stock, Energy, Groundwater, Water Quality, Rainwater, UWI agents.
Parameters:
| Param | Required | Values | Notes |
|---|---|---|---|
date1 | Yes | DD/MM/YYYY | Start date |
date2 | No | DD/MM/YYYY | End date — only for CUSTOM type |
category | Yes | SOURCE_CATEGORY, ENERGY_CATEGORY, STOCK_CATEGORY, GROUND_WATER_LEVEL, QUALITY_CATEGORY, RAIN_WATER_CATEGORY, ALL_CATEGORIES_V2|ENERGY_CATEGORY | Use pipe-separated for multi-category |
type | Yes | DAY, MONTH, YEAR, CUSTOM | Time granularity |
formattedOutput | No | true / false | Returns display-ready strings |
unitId | No | unit ID string | Filter to single device |
Type meanings:
| Type | What it returns | Data rows |
|---|---|---|
DAY | Hourly breakdown for a single day | ~33,744 rows across all units |
MONTH | Daily breakdown for a month | ~1,406 rows |
YEAR | Monthly breakdown for a year | <100 rows |
CUSTOM | Date range (date1 → date2) | Varies |
Response shape:
{
"categories": [
{
"categoryId": "SOURCE_CATEGORY",
"displayName": "Source",
"total": 1250.5,
"subCategories": [
{
"id": "sub_001",
"displayName": "Borewell",
"total": 800.0,
"units": [
{
"unitId": "unit_001",
"displayName": "Borewell 1",
"value": 450.0,
"online": true,
"lastUpdatedAt": "2026-03-03T10:30:00Z",
"meta": {
"flowFactor": 1.0,
"ir": 12000.0,
"fr": 12450.0,
"energySaved": null,
"offlineCount": 0,
"offlineDuration": 0,
"threshold": 500
},
"graph": [
{ "x": 0, "y": 12.5, "fr": 12012.5, "ir": 12000.0, "offlineCount": 0, "offlineDuration": 0 }
]
}
]
}
]
}
]
}
value at unit level IS the consumption for the requested period. Do not subtract ir from fr again — it is already done. Use value directly.
Always exclude VIRTUAL_CATEGORY units from device counts and offline analysis. They are calculated values, not physical sensors.
Water Balance API
GET /api/user/waterBalance/data
Used by: Water Balance Agent.
The Water Balance Agent must call /api/user/waterBalance/data. Using deviceDataV2 will return incorrect results.
Parameters:
| Param | Required | Values | Notes |
|---|---|---|---|
date1 | Yes | DD/MM/YYYY | The target date or month start |
type | Yes | HOUR or DATE | HOUR = specific day; DATE = monthly view |
date2 | No | DD/MM/YYYY | Only for date ranges |
divisionFactor | No | 1000 (default) | Converts litres to kL |
type selection rule:
| User asks about... | type to use |
|---|---|
| "today", a specific day (e.g., "20th November") | HOUR |
| "this month", "August", "last month", any month name | DATE |
Response shape:
{
"physical": {
"id": "physical",
"displayName": "Complete Plant",
"diagram": {
"nodes": [
{
"id": "node_001",
"unitId": "unit_001",
"data": {
"label": "Borewell 1",
"value": 450.5,
"online": true,
"meta": {
"dailyThreshold": 500,
"monthlyThreshold": 15000,
"thresholdReached": false,
"maxCapacity": 1000,
"percentage": 45.05
}
}
}
]
},
"summary": {
"nodes": [
{ "id": "water Balance", "data": { "label": "Water Balance", "value": 94.2 } },
{ "id": "Total source", "data": { "label": "Total Source", "value": 1250.0 } },
{ "id": "initial stock", "data": { "label": "Initial Stock", "value": 200.0 } },
{ "id": "final stock", "data": { "label": "Final Stock", "value": 180.0 } },
{ "id": "Total inflow", "data": { "label": "Total Inflow", "value": 1250.0 } },
{ "id": "total outflow", "data": { "label": "Total Outflow", "value": 1320.0 } },
{ "id": "measured consumption", "data": { "label": "Measured Consumption", "value": 1180.0 } },
{ "id": "actual consumption", "data": { "label": "Actual Consumption", "value": 1250.0 } },
{ "id": "difference", "data": { "label": "Difference", "value": 70.0 } }
]
}
},
"new_stp": { ... },
"treated_plant": { ... }
}
Page selection logic:
- User says "all" → analyse every diagram in the response
- User names a specific diagram → analyse only that one
- User doesn't specify → default to
physical(Complete Plant)
Water Balance % health ranges:
| Range | Status |
|---|---|
| Below 90% | Low / Poor — investigate losses |
| 90–100% | Healthy / Good (optimal) |
| Above 100% | Data quality issue — measurement error |
Virtual nodes are calculated values — they are not physical IoT devices. Never count virtual nodes as offline. Offline means online: false on a physical sensor node.
Water Neutrality API
GET /api/user/neutrality/
Used by: Water Neutrality Agent.
Unlike other endpoints, date1 and date2 are both mandatory.
Parameters:
| Param | Required | Values |
|---|---|---|
date1 | Yes | DD/MM/YYYY — period start |
date2 | Yes | DD/MM/YYYY — period end |
Response shape:
{
"ID_WATER_CREDITED": {
"total": 12500.0,
"displayTotal": "12,500 kL",
"subCategory": [
{
"id": "grey_water_trade",
"displayName": "Grey Water Trade",
"value": 8000.0,
"displayValue": "8,000 kL",
"normalizedValue": 0.64,
"target": 10000.0,
"units": []
}
]
},
"ID_WATER_DEBITED": {
"total": 18000.0,
"displayTotal": "18,000 kL",
"subCategory": [
{
"id": "borewell_1",
"displayName": "Borewell 1",
"value": 10000.0,
"displayValue": "10,000 kL",
"normalizedValue": 0.555,
"target": null,
"units": []
}
]
},
"waterNeutrality": 69.44,
"displayWaterNeutrality": "69.44%",
"summary": [
{ "label": "vs last month", "value": "+4.2%", "trend": "up" }
]
}
Key rules:
- Use
displayNamefor output — never hardcode source/sink names normalizedValueis the percentage contribution (0–1 range, multiply by 100 for %)- Always exclude the current incomplete month; use completed months only for trends
Neutrality score interpretation:
| Score | Status |
|---|---|
| < 25% | Critically Low |
| 25–50% | Low |
| 50–75% | Moderate |
| 75–100% | Good |
| ≥ 100% | Excellent — target achieved |
Alerts API
GET /api/user/alerts
Used by: Alerts Agent, Dashboard Agent (for alert counts).
Parameters:
| Param | Required | Values | Notes |
|---|---|---|---|
date | No | DD/MM/YYYY | Specific date filter |
alert_type | No | string | Filter by type |
Response structure — two buckets:
{
"today": [
{
"alertId": "alt_001",
"deviceName": "Borewell 1",
"unitId": "unit_001",
"alertType": "THRESHOLD",
"subType": "HIGH",
"message": "Flow exceeded threshold: 520 kL (limit: 500 kL)",
"timestamp": "2026-03-03T08:45:00Z",
"isRead": false,
"severity": "HIGH"
}
],
"currentMonth": [
{ ... }
]
}
For "this month" queries, use both today and currentMonth buckets, deduplicated by alertId. The get_all_alerts() helper handles this automatically.
Cross-month queries: If the user asks for "last 7 days" and it spans two calendar months, make two separate API calls — one for the previous month and one for the current month — then merge.
Critical distinction:
- Alerts API → alert event counts (how many threshold breaches)
deviceDataV2→ actual consumption / device status
Never use alerts to infer device consumption, and never use deviceDataV2 to count alert events.
Dashboard / Landing Page API
GET /landingPage/userData
Used by: Dashboard Agent for the overview snapshot.
Parameters:
| Param | Values | Notes |
|---|---|---|
date | DD/MM/YYYY | Date to fetch overview for |
type | YEAR, MONTH, DATE | Granularity |
pastThreeMonthsEnabled | true / false | Include 3-month trend |
summaryData | true / false | Include summary cards |
alertsEnabled | true / false | Include alert summary |
GET /api/user/standardCategoryView/ (trailing slash required)
Used by: Dashboard Agent for device online/offline counts by category.
Pass type: DATE — not type: DAY. This is a V1 API quirk.
Parameters:
| Param | Values |
|---|---|
type | DATE |
date1 | DD/MM/YYYY |
Response: Returns categories with unit-level online/offline status. Exclude VIRTUAL_CATEGORY from all device counts.
Note: ENERGY_CATEGORY is not included in standardCategoryView. Fetch it separately via deviceDataV2 with category: ENERGY_CATEGORY.
Reports API
GET /api/user/report
Used by: Reports Agent.
Parameters:
| Param | Required | Values | Notes |
|---|---|---|---|
reportType | Yes | water_balance, daily_summary, energy, water, quality, level, borewell, rain_water, consolidated | Report type |
service | Yes | Same as reportType | Matches reportType |
reportFormat | Yes | pdf, excel | Output format |
startDate | Yes | DD/MM/YYYY | |
endDate | No | DD/MM/YYYY | For range reports |
unitIds | No | comma-separated IDs | Filter to specific devices |
startTime | No | HH:MM | For hourly reports |
endTime | No | HH:MM | For hourly reports |
Returns raw bytes (file content) with a 120-second timeout.
Date validation rules — CRITICAL:
- Start date must be ≥ industry
startDatefrom session context - End date must be ≤ today
- No future dates
water_balanceanddaily_summaryreports for today are not appropriate (partial day) — ask the user if they want yesterday's instead
Permission check:
Before calling this endpoint, verify the requested service exists in session.context.reportsTab. If not present, the user does not have access to that report type.
Rainwater APIs
Three distinct APIs — do not confuse them:
- Rainfall / Precipitation
- Rainwater Efficiency
- Rain Flow Meters
GET /api/user/rainfall
Returns millimetres of rain recorded by rain gauges.
| Param | Values |
|---|---|
date1 | DD/MM/YYYY |
date2 | DD/MM/YYYY (optional) |
type | DAY, MONTH, YEAR, CUSTOM |
GET /api/user/rainfallEfficiency
Returns rainwater harvesting efficiency as a percentage.
| Param | Values |
|---|---|
date1 | DD/MM/YYYY |
date2 | DD/MM/YYYY (optional) |
Rain water flow meter volumes (kL) are fetched via deviceDataV2 with category: RAIN_WATER_CATEGORY. Do not use the rainfall endpoints for volume data.
Notifications API
GET /api/user/notification/
Used for: unread notification counts and notification history.
| Param | Default | Notes |
|---|---|---|
skip | 0 | Pagination offset |
limit | 20 | Items per page |
Date Utilities
All dates use DD/MM/YYYY format. The code runner pre-injects a parse_date() helper:
| Input string | Resolves to |
|---|---|
"today" | Today's date in DD/MM/YYYY |
"yesterday" | Yesterday |
"last week" | 7 days ago |
"last month" | First day of last month |
"01/06/2023" | Passed through unchanged |
Always validate that a requested date falls within [industry.startDate, today] before making an API call. Dates before the industry start date will return empty or error responses.
Summary API Contract (New System)
The new AI system requires a Summary API adapter layer in front of all the above endpoints. Every agent talks to summary endpoints — never raw data endpoints. Raw data rows are pre-aggregated server-side before the LLM ever sees them.
See the Implementation Guide for how to build this layer.
Target summary shape for each module:
{
"module": "water-flow",
"period": "last_30_days",
"total_kl": 118420,
"daily_avg_kl": 3940,
"peak": { "date": "14/02/2026", "value_kl": 6200, "source": "Borewell 1" },
"trend": "up 12% vs previous month",
"anomaly_count": 2,
"offline_devices": 1,
"breakdown": [
{ "name": "Borewell 1", "value_kl": 80000, "trend": "rising +18%" },
{ "name": "Tanker Inlet", "value_kl": 38420, "trend": "stable" }
]
}
This shape is consistent across all modules — the LLM reasons over summaries, never raw rows.