Skip to content

Blocks API

Block-level geospatial data and lookups. Blocks are administrative subdivisions within districts - there are roughly 220 blocks across all 35 districts in Assam. Each block carries dozens of indicator variables covering agriculture, water, infrastructure, livestock, and socio-economic factors.


Get All Blocks

Returns all blocks as a GeoJSON FeatureCollection with all variable data as feature properties. This is the primary data endpoint used by the map frontend.

GET /api/blocks
GET /api/blocks/geojson

Both paths return identical data.

Response

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "BLOCK_ID": "1234",
        "Block_name": "Digboi",
        "Dist_Name": "Tinsukia",
        "DISTRICT_I": "134",
        "AD": 45.2,
        "WA": 30.1,
        "CF": 62.3,
        "CI": 28.7
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [[[95.1, 27.3], [95.2, 27.3], [95.2, 27.4], [95.1, 27.3]]]
      }
    }
  ]
}

Key Property Fields

Field Type Description
BLOCK_ID string Unique block identifier
Block_name string Human-readable block name
Dist_Name string District name (mapped from DISTRICT_I)
DISTRICT_I string District ID code
Variable codes number Indicator values (AD, WA, CF, CI, etc.) - see Variables API for metadata

Geometry

Geometries are simplified (tolerance 0.001) for web performance. Coordinates are in WGS84 (EPSG:4326). For full-resolution geometries, access the raw shapefile directly.

Example

curl https://leaf-asrlm.in/api/blocks
import requests
import geopandas as gpd

response = requests.get("https://leaf-asrlm.in/api/blocks")
geojson = response.json()
print(f"Total blocks: {len(geojson['features'])}")

# Load into GeoPandas for analysis
gdf = gpd.GeoDataFrame.from_features(geojson['features'])
print(gdf[['Block_name', 'Dist_Name', 'AD']].head())
const response = await fetch('/api/blocks');
const geojson = await response.json();
console.log(`Total blocks: ${geojson.features.length}`);

// Add to Leaflet map
L.geoJSON(geojson).addTo(map);

Get Block by ID

Returns a single block's GeoJSON by its BLOCK_ID field.

GET /api/blocks/{block_id}

Parameters

Parameter In Type Required Description
block_id path string Yes The BLOCK_ID identifier

Response

Returns a GeoJSON FeatureCollection containing the single matching block with all properties and geometry.

Errors

Code Description
404 No block found with the given BLOCK_ID

Example

curl https://leaf-asrlm.in/api/blocks/1234
import requests

r = requests.get("https://leaf-asrlm.in/api/blocks/1234")
if r.status_code == 200:
    block = r.json()
    props = block['features'][0]['properties']
    print(f"Block: {props['Block_name']}, District: {props['Dist_Name']}")
else:
    print(f"Error: {r.json()['error']}")

Get Block by Name

Returns a single block's GeoJSON by its Block_name value.

GET /api/blocks/by-name/{block_name}

Parameters

Parameter In Type Required Description
block_name path string Yes Block name, case-sensitive (e.g. "Digboi")

Response

Returns a GeoJSON FeatureCollection for the matching block.

Errors

Code Description
404 No block found with the given name

Example

curl https://leaf-asrlm.in/api/blocks/by-name/Digboi
import requests

r = requests.get("https://leaf-asrlm.in/api/blocks/by-name/Digboi")
block = r.json()
print(f"Features: {len(block['features'])}")
const name = 'Digboi';
const r = await fetch(`/api/blocks/by-name/${encodeURIComponent(name)}`);
const block = await r.json();
console.log(block.features[0].properties);

URL Encoding

Block names with spaces must be URL-encoded (e.g., Doom%20Dooma). Most HTTP libraries handle this automatically.


Get SHG Summary for a Block

Aggregates the village-level SHG form data (Kobo export) for one block. Returned shape drives the right-side summary panel in the Cluster Planner.

Blocks absent from the Kobo export fall back to the village master (villages.csv) aggregates: same shape with "source": "village_master", and empty other / activities_raw (the master has no per-activity breakdown).

GET /api/blocks/{block_name}/shg-summary

Parameters

Parameter In Type Required Description
block_name path string Yes Block name, case-insensitive (e.g. NAHARKATIA).

Response

{
  "district_name": "DIBRUGARH",
  "block_name": "NAHARKATIA",
  "available": true,
  "villages_total": 190,
  "villages_with_gps": 175,
  "villages_without_gps": 15,
  "gp_count": 13,
  "gps": ["BALIMORA", "DHADUMIA", "..."],
  "members_total": 13919,
  "commodities": {
    "Dairy": 206,
    "Goatery": 4452,
    "Piggery": 3594,
    "Backyard_Poultry": 3852,
    "Duckery": 1277,
    "Fishery_Activity": 366
  },
  "other": {
    "Fodder cultivation": 3,
    "Feed manufacturing": 1,
    "Livestock transport": 1,
    "Meat shop": 167
  },
  "activities_raw": {
    "dairy_production": 206,
    "goat_farming": 4267,
    "...": "..."
  }
}

When the block is in neither the Kobo export nor the village master, the response is {"block_name": "...", "available": false}.

Field Notes

Field Description
villages_total Unique villages submitted from this block.
villages_with_gps / villages_without_gps Of villages_total, how many carry lat/long. Only with-GPS villages are plotted on the map.
commodities Sum of SHG members across the form's sub-activities mapped into each of the 6 clustering commodities.
other Activities outside the 6 commodities (fodder, feed mfg, transport, meat shop).
activities_raw All 25 raw form activity totals — useful for ad-hoc charts.

Example

curl https://leaf-asrlm.in/api/blocks/NAHARKATIA/shg-summary
const r = await fetch(`/api/blocks/${encodeURIComponent(block)}/shg-summary`);
const summary = await r.json();
if (summary.available) renderPanel(summary);

Get Block Convergence

Returns the block's values for the variables the client tagged Biophysical or Infrastructure in the dss_input sheet's convergence tag column — the second Cluster column (column P, read as Cluster.1). Drives the Biophysical and Infrastructure (convergence) cards on the cluster drill-down.

GET /api/blocks/{block_name}/convergence

Parameters

Parameter In Type Required Description
block_name path string Yes Block name, case-insensitive (e.g. Bajali).

Response

{
  "block_name": "Bajali",
  "available": true,
  "biophysical": [
    { "code": "E", "label": "% villages with community rainwater harvesting system", "value": 10.71 }
  ],
  "infrastructure": [
    { "code": "S", "label": "% Villages connected to all weather road (< 5 km)", "value": 83.33 }
  ]
}

Field Notes

Field Description
available true once the block is found in the block_values sheet.
biophysical / infrastructure One entry per tagged variable: code (the I_variable), label (I_label), and value (the block's value, rounded; null when the block has no value for that code).

Both lists are empty when the sheet has no convergence tags yet (not an error). Tags are deduped by code (first occurrence wins).

Example

curl https://leaf-asrlm.in/api/blocks/Bajali/convergence
const r = await fetch(`/api/blocks/${encodeURIComponent(block)}/convergence`);
const conv = await r.json();
renderConvergenceCards(conv.biophysical, conv.infrastructure);

Get Block Statistics

Returns aggregate statistics for the block dataset including district distribution and available data columns.

GET /api/blocks/statistics
GET /api/statistics

Both paths return identical data.

Response

{
  "total_blocks": 220,
  "districts": {
    "Tinsukia": 8,
    "Dibrugarh": 7,
    "Jorhat": 6,
    "Kamrup Metropolitan": 5
  },
  "district_count": 35,
  "columns": ["BLOCK_ID", "Block_name", "Dist_Name", "DISTRICT_I", "AD", "WA", "CF", "CI"]
}

Counts come from the block shapefile

total_blocks, districts, and district_count are computed live from the loaded block shapefile (load_shapefile()), grouped by Dist_Name. Values shown here are illustrative; Assam currently has 35 districts and roughly 220 blocks.

Field Type Description
total_blocks integer Total number of blocks in the dataset
districts object Block count per district (key: district name, value: count)
district_count integer Number of distinct districts
columns array All available data columns (excluding geometry)

Example

curl https://leaf-asrlm.in/api/blocks/statistics
import requests

r = requests.get("https://leaf-asrlm.in/api/blocks/statistics")
stats = r.json()
print(f"Total blocks: {stats['total_blocks']}")
print(f"Districts: {stats['district_count']}")
print(f"Variables available: {len(stats['columns'])}")

# Top 5 districts by block count
sorted_districts = sorted(stats['districts'].items(), key=lambda x: x[1], reverse=True)
for name, count in sorted_districts[:5]:
    print(f"  {name}: {count} blocks")

Use for Discovery

The columns field is useful for discovering which variables are available before calling the Variables API for full metadata.