Auchindown · Rooftop Solar Inventory

API Reference

Reference spec for the rooftop solar detection product’s data API. Hosted at solar.auchindown.com.
Solar Inventory Map →     Pricing calculator →

Base URL

https://solar.auchindown.com/v1/solar/{country}/...
{country} is an ISO 3166-1 alpha-3 code, lowercase (e.g. jam for Jamaica).

Conventions

Auth

Every endpoint requires Authorization: Bearer <api_key>. Missing or invalid keys return 401.

Epochs

Imagery epochs are identified by strings like 2026-04, matching the April/October capture cadence. Any endpoint accepting an epoch query parameter defaults to the latest available epoch when omitted.

Response format

Spatial endpoints return raw GeoJSON: a valid FeatureCollection or Feature at the top level, so responses drop directly into GIS tooling (QGIS, MapLibre) without unwrapping. Pagination and link metadata are added as extra top-level members, following the OGC API - Features convention:
{
  "type": "FeatureCollection",
  "features": [ /* ... */ ],
  "numberMatched": 240,
  "numberReturned": 50,
  "links": [
    { "rel": "self", "href": "https://solar.auchindown.com/v1/solar/jam/tiles?limit=50" },
    { "rel": "next", "href": "https://solar.auchindown.com/v1/solar/jam/tiles?limit=50&cursor=..." }
  ]
}
Non-spatial endpoints (/epochs, /tiles/{id}/stats, /summary) return plain JSON.

Pagination

Spatial list endpoints accept limit (default 50, max 500) and cursor.

Errors

Every non-2xx response has the same body shape:
{ "error": { "code": "invalid_bbox", "message": "bbox must be minLon,minLat,maxLon,maxLat" } }

Endpoints

GET/tiles
List tile boundaries and available epochs for each tile.

Query parameters

ParamTypeNotes
bboxminLon,minLat,maxLon,maxLatOptional spatial filter
limitintegerDefault 50, max 500
cursorstringOpaque pagination cursor

Response

FeatureCollection of tile polygons (each tile is the fixed 2.5×2.5 km / 6.25 km² grid cell).
{
  "grid_id": "311-257",
  "available_epochs": ["2026-04", "2025-10"]
}
Errors: 400 invalid bbox or unknown epoch.
GET/tiles/{id}
Fetch a single tile. {id} is the tile’s grid_id.

Query parameters

ParamTypeNotes
epochstringOptional, defaults to latest

Response

A single GeoJSON Feature (the tile polygon), properties shaped exactly as in the /tiles list.
Errors: 404 unknown tile; 400 unknown epoch for that tile.
GET/epochs
List available imagery epochs for the country.

Response

Plain JSON array, no pagination:
[
  {
    "epoch": "2025-10",
    "captured_start": "2025-08-21",
    "captured_end": "2025-09-20",
    "tile_coverage_count": 5,
    "status": "complete"
  },
  {
    "epoch": "2026-04",
    "captured_start": "2025-12-17",
    "captured_end": "2026-02-22",
    "tile_coverage_count": 15,
    "status": "complete"
  }
]
GET/tiles/{id}/stats?epoch=
Full tile statistics: the same data rendered on the printable tile report sheet.

Response

Plain JSON object, field-for-field identical to the live product’s TileStats interface, plus epoch:
{
  "grid_id": "311-257",
  "parishes": "Kingston",
  "settlement_class": "Class A",
  "communities": "Harbour View",
  "cell_area_m2": 6250000,
  "land_area_m2": 5100000,
  "urban_area_m2": 4300000,
  "rural_area_m2": 800000,
  "water_area_m2": 1150000,
  "total_building_count": 971,
  "number_of_buildings_with_solar": 42,
  "total_residential_building_count": 890,
  "total_non_residential_building_count": 81,
  "number_of_residential_buildings_with_solar": 35,
  "number_of_non_residential_buildings_with_solar": 7,
  "residential_panel_area_m2": 980.5,
  "non_residential_panel_area_m2": 486.2,
  "total_panel_area_m2": 1466.7,
  "installed_capacity_mw": 0.22,
  "residential_capacity_mw": 0.147,
  "non_residential_capacity_mw": 0.073,
  "residential_penetration_pct": 3.9,
  "non_residential_penetration_pct": 8.6,
  "overall_utilisation_pct": 23.5,
  "epoch": "2026-04"
}
Errors: 404 unknown tile; 400 unknown epoch.
GET/tiles/{id}/installations?epoch=
Individual detected installations within a tile.

Query parameters

ParamTypeNotes
epochstringDefaults to latest
bboxminLon,minLat,maxLon,maxLatSub-filter within the tile
building_classresidential | non_residentialOptional
limitintegerDefault 50, max 500
cursorstringOpaque pagination cursor

Response

FeatureCollection. Each feature’s properties:
{
  "installation_id": "inst_9f2a1c",
  "building_id": "bldg_44210",
  "panel_area_m2": 18.4,
  "capacity_kw": 2.76,
  "building_class": "residential",
  "epoch": "2026-04"
}
capacity_kw is derived from panel area using the same watts/m² constant as the live product.
Errors: 404 unknown tile; 400 invalid bbox/epoch/confidence.
GET/tiles/{id}/changes?from=&to=
Change detection between two epochs for a tile.

Query parameters

ParamTypeNotes
fromstringRequired epoch identifier
tostringRequired; must postdate from
changed_onlybooleanOptional, default false. When true, excludes unchanged installations; only appeared, disappeared, expanded, and contracted are returned.

Response

FeatureCollection of installations, each with change metadata added:
{
  "installation_id": "inst_9f2a1c",
  "building_id": "bldg_44210",
  "change_type": "expanded",
  "panel_area_m2_from": 12.0,
  "panel_area_m2_to": 18.4,
  "building_class": "residential"
}
change_type is one of appeared, disappeared, expanded, contracted, unchanged.
Errors: 400 if from/to are missing, unknown, or from does not predate to; 404 unknown tile.
GET/installations?bbox=&epoch=
Cross-tile installation query.

Query parameters

ParamTypeNotes
bboxminLon,minLat,maxLon,maxLatRequired
epochstringDefaults to latest
building_classresidential | non_residentialOptional
limitintegerDefault 50, max 500
cursorstringOpaque pagination cursor

Response

Same shape as /tiles/{id}/installations, with a grid_id property added to each feature so results trace back to their tile.
Errors: 400 if bbox is missing or its area exceeds a maximum (e.g. 100 km²); this endpoint does not support unbounded, country-wide dumps; use /tiles + per-tile /installations for bulk export instead.
GET/summary?epoch=
National (or grouped) rollup.

Query parameters

ParamTypeNotes
epochstringDefaults to latest
groupbyparish | settlement_classOptional

Response

Plain JSON. Without groupby, a single object in the same metric shape as /tiles/{id}/stats (minus tile-identifying fields), summed across all tiles. With groupby, an array of { group_key, ...same metrics }.