Skip to main content

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 IDWhat It Covers
SOURCE_CATEGORYWater flow meters (sources + consumption points)
ENERGY_CATEGORYEnergy meters
STOCK_CATEGORYStorage tanks (sumps, overhead tanks, reservoirs)
GROUND_WATER_LEVELGroundwater level sensors (water table depth)
QUALITY_CATEGORYWater quality sensors (pH, TDS, COD, BOD, etc.)
RAIN_WATER_CATEGORYRain gauges
VIRTUAL_CATEGORYCalculated/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:

ParamRequiredValuesNotes
date1YesDD/MM/YYYYStart date
date2NoDD/MM/YYYYEnd date — only for CUSTOM type
categoryYesSOURCE_CATEGORY, ENERGY_CATEGORY, STOCK_CATEGORY, GROUND_WATER_LEVEL, QUALITY_CATEGORY, RAIN_WATER_CATEGORY, ALL_CATEGORIES_V2|ENERGY_CATEGORYUse pipe-separated for multi-category
typeYesDAY, MONTH, YEAR, CUSTOMTime granularity
formattedOutputNotrue / falseReturns display-ready strings
unitIdNounit ID stringFilter to single device

Type meanings:

TypeWhat it returnsData rows
DAYHourly breakdown for a single day~33,744 rows across all units
MONTHDaily breakdown for a month~1,406 rows
YEARMonthly breakdown for a year<100 rows
CUSTOMDate 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 }
]
}
]
}
]
}
]
}
Critical — Values are NOT cumulative

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.

Virtual devices

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.

Use this endpoint, not deviceDataV2

The Water Balance Agent must call /api/user/waterBalance/data. Using deviceDataV2 will return incorrect results.

Parameters:

ParamRequiredValuesNotes
date1YesDD/MM/YYYYThe target date or month start
typeYesHOUR or DATEHOUR = specific day; DATE = monthly view
date2NoDD/MM/YYYYOnly for date ranges
divisionFactorNo1000 (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 nameDATE

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:

  1. User says "all" → analyse every diagram in the response
  2. User names a specific diagram → analyse only that one
  3. User doesn't specify → default to physical (Complete Plant)

Water Balance % health ranges:

RangeStatus
Below 90%Low / Poor — investigate losses
90–100%Healthy / Good (optimal)
Above 100%Data quality issue — measurement error
Virtual nodes vs offline devices

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.

Both dates required

Unlike other endpoints, date1 and date2 are both mandatory.

Parameters:

ParamRequiredValues
date1YesDD/MM/YYYY — period start
date2YesDD/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 displayName for output — never hardcode source/sink names
  • normalizedValue is 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:

ScoreStatus
< 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:

ParamRequiredValuesNotes
dateNoDD/MM/YYYYSpecific date filter
alert_typeNostringFilter 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": [
{ ... }
]
}
Always merge both buckets

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:

ParamValuesNotes
dateDD/MM/YYYYDate to fetch overview for
typeYEAR, MONTH, DATEGranularity
pastThreeMonthsEnabledtrue / falseInclude 3-month trend
summaryDatatrue / falseInclude summary cards
alertsEnabledtrue / falseInclude alert summary

GET /api/user/standardCategoryView/ (trailing slash required)

Used by: Dashboard Agent for device online/offline counts by category.

Use type: DATE (not DAY)

Pass type: DATE — not type: DAY. This is a V1 API quirk.

Parameters:

ParamValues
typeDATE
date1DD/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:

ParamRequiredValuesNotes
reportTypeYeswater_balance, daily_summary, energy, water, quality, level, borewell, rain_water, consolidatedReport type
serviceYesSame as reportTypeMatches reportType
reportFormatYespdf, excelOutput format
startDateYesDD/MM/YYYY
endDateNoDD/MM/YYYYFor range reports
unitIdsNocomma-separated IDsFilter to specific devices
startTimeNoHH:MMFor hourly reports
endTimeNoHH:MMFor hourly reports

Returns raw bytes (file content) with a 120-second timeout.

Date validation rules — CRITICAL:

  • Start date must be ≥ industry startDate from session context
  • End date must be ≤ today
  • No future dates
  • water_balance and daily_summary reports 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:

GET /api/user/rainfall

Returns millimetres of rain recorded by rain gauges.

ParamValues
date1DD/MM/YYYY
date2DD/MM/YYYY (optional)
typeDAY, MONTH, YEAR, CUSTOM

Notifications API

GET /api/user/notification/

Used for: unread notification counts and notification history.

ParamDefaultNotes
skip0Pagination offset
limit20Items per page

Date Utilities

All dates use DD/MM/YYYY format. The code runner pre-injects a parse_date() helper:

Input stringResolves 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.