Production Tool API¶
Two-way integration with the external production tool that downstream partners are building. The contract per the IWMI requirements call (2026-04-23):
- Outbound (we publish): finalised clusters with their villages, members, and assigned coordinators.
- Inbound (they push): aggregated dashboard data per cluster (e.g. for a duckery cluster: eggs produced, meat output). Per-user filtering and authentication live in the production tool - only aggregates flow back to LEAF DSS.
A cluster only appears in the outbound feed once it has been finalised - typically after the CSV edit cycle has stabilised the village list.
No authentication
These endpoints are unauthenticated, like the rest of the LEAF DSS API. There is no API key or token; the production tool reaches them directly over HTTPS. Do not expose the writable routes (finalize, dashboard POST) to untrusted callers.
Finalise a Cluster¶
Sets the cluster's finalized flag. Pass {"finalized": false} to revert (e.g. if further edits are needed). Setting finalized=true also protects the cluster from automatic regeneration by the coverage sweep and on-view smart refresh.
Path Parameters¶
| Param | Type | Required | Description |
|---|---|---|---|
cluster_id |
string | Yes | Cluster ID, e.g. KHOWANG-Goatery-39e1bdee. |
Body¶
finalized defaults to true if the body is omitted or is not valid JSON.
Response¶
Returns the full updated cluster record.
{
"cluster_id": "KHOWANG-Goatery-39e1bdee",
"commodity": "Goatery",
"block_name": "KHOWANG",
"district_name": "DIBRUGARH",
"total_members": 49,
"max_span_km": 1.193,
"centroid_lat": 27.204,
"centroid_lon": 94.808,
"pashu_sakhi": "Smt. R. Devi",
"block_coordinator": "Sri B. Sarma",
"district_coordinator": "Sri K. Das",
"cluster_name": null,
"finalized": true,
"locked": false,
"provisional": false,
"dashboard": null,
"villages": [
{
"vill_name": "Example Village",
"gp_name": "Example GP",
"lat": 27.201,
"long": 94.805,
"members": 12,
"village_index": 3
}
],
"village_indices": [3],
"cluster_num": 1,
"cluster_label": "1",
"cluster_code": "DI-KH-GO-01"
}
| Code | Description |
|---|---|
200 |
Updated cluster record. |
404 |
Cluster ID not found. |
Outbound Clusters Feed¶
Read-only list of finalised clusters (those with finalized=true). The production tool calls this whenever it needs to refresh its cluster catalogue. Same scope filters as /api/clusters.
Query Parameters¶
| Param | Type | Required | Description |
|---|---|---|---|
block |
string | No | Filter by block name. |
district |
string | No | Filter by district name. |
commodity |
string | No | One of the six commodities: Dairy, Goatery, Piggery, Backyard_Poultry, Duckery, Fishery_Activity. |
Response¶
An array of cluster records (same shape as the finalize response). Only clusters with finalized=true are included; filters narrow the set further.
[
{
"cluster_id": "KHOWANG-Goatery-39e1bdee",
"commodity": "Goatery",
"block_name": "KHOWANG",
"district_name": "DIBRUGARH",
"total_members": 49,
"max_span_km": 1.193,
"centroid_lat": 27.204,
"centroid_lon": 94.808,
"pashu_sakhi": "Smt. R. Devi",
"block_coordinator": "Sri B. Sarma",
"district_coordinator": "Sri K. Das",
"cluster_name": null,
"finalized": true,
"locked": false,
"provisional": false,
"dashboard": null,
"villages": [ /* ... */ ],
"village_indices": [3],
"cluster_num": 1,
"cluster_label": "1",
"cluster_code": "DI-KH-GO-01"
}
]
| Code | Description |
|---|---|
200 |
Array of finalised clusters (empty array if none match). |
Example¶
Cluster Production Dashboard¶
POST accepts an arbitrary JSON payload and stores it on the cluster under dashboard. GET returns the last stored payload (or {} if none). Schema is intentionally open - the production tool sends whatever its commodity dashboard produces; LEAF DSS surfaces it on the cluster report card without inspection.
Posting a dashboard locks the cluster
A successful POST also sets the cluster's locked flag to true. Once a cluster carries production-tool dashboard data it is treated as operational/human-owned and is never silently regenerated by the coverage sweep or the on-view smart refresh (which would otherwise drop the payload).
Path Parameters¶
| Param | Type | Required | Description |
|---|---|---|---|
cluster_id |
string | Yes | Cluster ID to attach the dashboard payload to. |
Example POST Body¶
Response¶
For both GET and POST, returns the stored dashboard payload object directly (not the full cluster record). GET returns {} when nothing has been posted yet.
| Code | Description |
|---|---|
200 |
Dashboard payload returned (empty object if not yet posted). |
400 |
POST without a valid JSON body. |
404 |
Cluster not found. |
Example¶
# Push aggregates
curl -X POST https://leaf-asrlm.in/api/production-tool/dashboard/KHOWANG-Duckery-abc12345 \
-H "Content-Type: application/json" \
-d '{"period":"2026-Q1","eggs_produced":12450,"meat_kg":320.5}'
# Read latest
curl https://leaf-asrlm.in/api/production-tool/dashboard/KHOWANG-Duckery-abc12345
const base = "https://leaf-asrlm.in/api/production-tool/dashboard/KHOWANG-Duckery-abc12345";
// Push aggregates
await fetch(base, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ period: "2026-Q1", eggs_produced: 12450, meat_kg: 320.5 }),
});
// Read latest
const dashboard = await (await fetch(base)).json();