Docs › API reference › Maps & seasons
Maps & seasons
Parcels, zones, farmers, seasons, map layers — the farm's spatial data foundation.
34 operations · base /api/v1/gis
/api/v1/gis/care-schedulesCare schedule triggers (filter by parcel)
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
parcelId | GUID | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/care-schedules" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
[
{
"assignee_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"created_at": "2026-10-28T07:30:00Z",
"delivery": "…",
"enabled": true,
"enabled_at": "2026-10-28T07:30:00Z",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"notify_user_ids": [
"0190a3c2-5b1e-7c3d-8e4f-000000000001"
],
"parcel_code": "…",
"parcel_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"plot_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"plot_name": "…",
"season_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"template_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"template_name": "…"
}
]/api/v1/gis/care-schedules/previewPreview the schedule (writes nothing)
`from` yyyy-MM-dd (defaults to today, Vietnam time), `days` 1–400 (default 30).
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
templateId | GUID | query | no | — |
parcelId | GUID | query | no | — |
plotId | GUID | query | no | — |
seasonId | GUID | query | no | — |
from | string | query | no | — |
days | int | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/care-schedules/preview" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"from": "…",
"items": [
{
"anchor": "…",
"due_on": "…",
"material": "…",
"quantity": 1.5,
"rule_key": "…",
"task_type": "…",
"title": "…",
"trees": 1,
"unit": "…",
"unknown_age_trees": 1
}
],
"to": "…",
"warnings": [
"…"
],
"weeks": [
{
"items": [
{
"anchor": "…",
"due_on": "…",
"material": "…",
"quantity": 1.5,
"rule_key": "…",
"task_type": "…",
"title": "…",
"trees": 1,
"unit": "…",
"unknown_age_trees": 1
}
],
"week_end": "…",
"week_start": "…"
}
]
}/api/v1/gis/care-schedules/this-weekThis week's care tasks (ENABLED triggers only)
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
parcelId | GUID | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/care-schedules/this-week" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"plots": [
{
"activation_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"delivery": "…",
"items": [
{
"anchor": "…",
"due_on": "…",
"material": "…",
"quantity": 1.5,
"rule_key": "…",
"task_type": "…",
"title": "…",
"trees": 1,
"unit": "…",
"unknown_age_trees": 1
}
],
"parcel_code": "…",
"parcel_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"plot_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"plot_name": "…",
"template_name": "…"
}
],
"week_end": "…",
"week_start": "…"
}/api/v1/gis/care-schedules/{id}/calendarFull-year schedule of a trigger
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
year | int | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/care-schedules/<id>/calendar" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"from": "…",
"items": [
{
"anchor": "…",
"due_on": "…",
"material": "…",
"quantity": 1.5,
"rule_key": "…",
"task_type": "…",
"title": "…",
"trees": 1,
"unit": "…",
"unknown_age_trees": 1
}
],
"to": "…",
"warnings": [
"…"
],
"weeks": [
{
"items": [
{
"anchor": "…",
"due_on": "…",
"material": "…",
"quantity": 1.5,
"rule_key": "…",
"task_type": "…",
"title": "…",
"trees": 1,
"unit": "…",
"unknown_age_trees": 1
}
],
"week_end": "…",
"week_start": "…"
}
]
}/api/v1/gis/care-schedules/{id}/generationsGenerated history of a trigger
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/care-schedules/<id>/generations" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
[
{
"activation_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"created_at": "2026-10-28T07:30:00Z",
"delivery": "…",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"item_count": 1,
"week_end": "…",
"week_start": "…"
}
]/api/v1/gis/crop-typesList crop types
Filter by category (fruit_tree/cereal/vegetable/industrial/other), isActive. Paginated.
gis.crop-types.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
category | string | query | no | — |
isActive | bool | query | no | — |
page | int | query | no | — |
pageSize | int | query | no | — |
deleted | bool | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/crop-types" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"items": [
{
"bearing_age_years": 1,
"category": "…",
"code": "…",
"effective_lifecycle": "…",
"grow_days": 1,
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"is_active": true,
"lifecycle": "…",
"lifecycle_guessed": true,
"name": "…"
}
],
"page": 1,
"page_size": 1,
"page_size_capped": true,
"total": 1
}/api/v1/gis/crop-types/{id}Get a crop type by ID
Used by nextfarm-harvest to get the crop type name when building a harvest record.
gis.crop-types.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/crop-types/<id>" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"category": "…",
"code": "…",
"created_at": "2026-10-28T07:30:00Z",
"grow_days": 1,
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"is_active": true,
"name": "…",
"updated_at": "2026-10-28T07:30:00Z"
}/api/v1/gis/crop-types/{id}/perennial-profilePerennial crop profile of a species
Life cycle, bearing age, default planting spacing, template life stages.
gis.crop-types.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/crop-types/<id>/perennial-profile" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"bearing_age_years": 1,
"crop_type_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"default_row_spacing_m": 1.5,
"default_tree_spacing_m": 1.5,
"effective_lifecycle": "…",
"life_stages": [
{
"code": "…",
"from_year": 1,
"name": "…",
"to_year": 1
}
],
"lifecycle": "…",
"lifecycle_guessed": true
}/api/v1/gis/crop-types/{id}/varietiesVarieties and rootstocks of a species
kind = variety | rootstock; empty = both.
gis.crop-types.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
kind | string | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/crop-types/<id>/varieties" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
[
{
"code": "…",
"crop_type_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"kind": "…",
"name": "…",
"note": "…"
}
]/api/v1/gis/facilitiesList livestock facilities
Filter by facilityType (barn, pasture, feedlot, dairy, poultry_house, piggery, processing_plant, other), status (active, inactive, maintenance) and branchId. Paginated.
gis.facilities.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
facilityType | string | query | no | — |
status | string | query | no | — |
sourceParcelId | GUID | query | no | — |
branchId | GUID | query | no | — |
page | int | query | no | — |
pageSize | int | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/facilities" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"items": [
{
"area_ha": 1.5,
"boundary_geo_json": "…",
"branch_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"capacity": 1,
"created_at": "2026-10-28T07:30:00Z",
"current_stock": 1,
"facility_code": "…",
"facility_type": "…",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"name": "…",
"source_parcel_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"status": "…",
"zone_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"zone_name": "…"
}
],
"page": 1,
"page_size": 1,
"page_size_capped": true,
"total": 1
}/api/v1/gis/facilities/{id}Get a livestock facility
Returns full details including GeoJSON boundary, metadata, capacity, current_stock.
gis.facilities.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/facilities/<id>" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"area_ha": 1.5,
"boundary_geo_json": "…",
"branch_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"capacity": 1,
"created_at": "2026-10-28T07:30:00Z",
"current_stock": 1,
"facility_code": "…",
"facility_type": "…",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"metadata": "…",
"name": "…",
"source_parcel_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"status": "…",
"updated_at": "2026-10-28T07:30:00Z",
"zone_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"zone_name": "…"
}/api/v1/gis/farmer-groupsGET /api/v1/gis/farmer-groups
gis.farmers.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
includeInactive | bool | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/farmer-groups" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
[
{
"code": "…",
"farmer_count": 1,
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"is_active": true,
"leader_farmer_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"name": "…",
"note": "…",
"zone_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001"
}
]/api/v1/gis/farmersList farmers
Filter by zone_id. Paginated.
gis.farmers.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
zoneId | GUID | query | no | — |
page | int | query | no | — |
pageSize | int | query | no | — |
deleted | bool | query | no | — |
groupId | GUID | query | no | — |
memberType | string | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/farmers" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"items": [
{
"address": "…",
"cooperative_name": "…",
"full_name": "…",
"group_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"group_name": "…",
"home_location_geo_json": "…",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"identity_number": "…",
"member_type": "…",
"phone": "…",
"zone_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"zone_name": "…"
}
],
"page": 1,
"page_size": 1,
"page_size_capped": true,
"total": 1
}/api/v1/gis/farmers/{id}Get a farmer
Returns full details + zone name + home location (GeoJSON Point).
gis.farmers.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/farmers/<id>" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"address": "…",
"cooperative_name": "…",
"created_at": "2026-10-28T07:30:00Z",
"full_name": "…",
"group_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"group_name": "…",
"home_location_geo_json": "…",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"identity_number": "…",
"member_type": "…",
"phone": "…",
"public_consent_at": "2026-10-28T07:30:00Z",
"public_consent_by": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"public_name_consent": true,
"public_phone_consent": true,
"updated_at": "2026-10-28T07:30:00Z",
"zone_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"zone_name": "…"
}/api/v1/gis/layersDanh sách map layers
Filter by layer_type (ndvi/satellite/custom/soil/weather), zone_id, status (processing/ready/failed/archived). Paginated.
gis.layers.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
layerType | string | query | no | — |
zoneId | GUID | query | no | — |
status | string | query | no | — |
page | int | query | no | — |
pageSize | int | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/layers" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"items": [
{
"captured_at": "2026-10-28",
"created_at": "2026-10-28T07:30:00Z",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"layer_type": "…",
"name": "…",
"source_url": "…",
"status": "…",
"zone_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"zone_name": "…"
}
],
"page": 1,
"page_size": 1,
"page_size_capped": true,
"total": 1
}/api/v1/gis/layers/{id}Get a map layer
Returns full details + zone name + ndvi stats + style_config jsonb.
gis.layers.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/layers/<id>" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"captured_at": "2026-10-28",
"created_at": "2026-10-28T07:30:00Z",
"file_path": "…",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"layer_type": "…",
"name": "…",
"ndvi_avg": 1.5,
"ndvi_max": 1.5,
"ndvi_min": 1.5,
"source_url": "…",
"status": "…",
"style_config": "…",
"updated_at": "2026-10-28T07:30:00Z",
"zone_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"zone_name": "…"
}/api/v1/gis/map/pointsLightweight points by bbox: farmer homes + parcel centroids
bbox=minLon,minLat,maxLon,maxLat (required, max 10°×10°). zoom 0..22 (optional): below 13 with more than limit results, returns mode=clusters (grid cells). limit defaults to 2000, cap 5000; when exceeded, results are cut and truncated=true (NO error). kind=all|farmer|parcel. Household points are included only when the caller also has gis.farmers.view and is not restricted to owned parcels.
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
bbox | string | query | no | — |
zoom | int | query | no | — |
limit | int | query | no | — |
kind | string | query | no | — |
zoneId | GUID | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/map/points" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"clusters": [
{
"count": 1,
"latitude": 1.5,
"longitude": 1.5
}
],
"limit": 1,
"mode": "…",
"points": [
{
"area_ha": 1.5,
"farmer_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"kind": "…",
"latitude": 1.5,
"longitude": 1.5,
"name": "…",
"parcel_code": "…",
"parcel_count": 1,
"status": "…"
}
],
"total": 1,
"truncated": true,
"zoom": 1
}/api/v1/gis/parcelsList parcels
Filter by bbox (minLon,minLat,maxLon,maxLat), zoneId, ownerId, cropTypeId, status, branchId. Paginated. Bbox at most 2°×2°, up to 1000 results.
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
bbox | string | query | no | — |
zoneId | GUID | query | no | — |
ownerId | GUID | query | no | — |
cropTypeId | GUID | query | no | — |
status | string | query | no | — |
branchId | GUID | query | no | — |
page | int | query | no | — |
pageSize | int | query | no | — |
deleted | bool | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/parcels" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"items": [
{
"active_season_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"active_season_name": "…",
"active_seasons": [
{
"crop_type_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"kind": "…",
"name": "…",
"plot_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001"
}
],
"area_ha": 1.5,
"boundary_geo_json": "…",
"branch_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"created_at": "2026-10-28T07:30:00Z",
"crop_type_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"crop_type_name": "…",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"latitude": 1.5,
"longitude": 1.5,
"owner_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"owner_name": "…",
"parcel_code": "…",
"status": "…",
"zone_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"zone_name": "…"
}
],
"page": 1,
"page_size": 1,
"page_size_capped": true,
"total": 1
}/api/v1/gis/parcels/summaryParcel area summary by household / zone / crop
group_by = owner (by household) | zone (by zone) | crop (by crop type). Each row: household count, parcel count, total area (excluding parcels with invalid boundaries), number of parcels WITHOUT a boundary. Additional filters: zoneId, cropTypeId, status. Paginated (max 200 rows/page), sorted by total area descending. Same visibility scope as the parcel list.
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
group_by | string | query | no | — |
zoneId | GUID | query | no | — |
cropTypeId | GUID | query | no | — |
status | string | query | no | — |
page | int | query | no | — |
pageSize | int | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/parcels/summary" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"items": [
{
"estimated_area_ha": 1.5,
"excluded_area_ha": 1.5,
"farmer_count": 1,
"implausible_count": 1,
"key": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"name": "…",
"parcel_count": 1,
"parcels_without_boundary_count": 1,
"total_area_ha": 1.5
}
],
"page": 1,
"page_size": 1,
"page_size_capped": true,
"total": 1
}/api/v1/gis/parcels/{id}Get a parcel
Returns full details including GeoJSON boundary + nested zone/owner/crop_type + ndvi_history.
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/parcels/<id>" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"area_ha": 1.5,
"boundary_geo_json": "…",
"branch_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"created_at": "2026-10-28T07:30:00Z",
"crop_type": {
"category": "…",
"code": "…",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"name": "…"
},
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"latitude": 1.5,
"longitude": 1.5,
"ndvi_history": [
{
"ndvi_value": 1.5,
"recorded_at": "2026-10-28"
}
],
"owner": {
"full_name": "…",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"phone": "…",
"public_name_consent": true,
"public_phone_consent": true
},
"parcel_code": "…",
"status": "…",
"updated_at": "2026-10-28T07:30:00Z",
"zone": {
"code": "…",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"name": "…",
"zone_type": "…"
}
}/api/v1/gis/parcels/{id}/contains-pointCheck whether a GPS point is inside a parcel boundary
Returns 200 with `{ parcel_id, inside }`. BEING OUTSIDE THE BOUNDARY IS A VALID ANSWER (`inside=false`), NOT an error — this endpoint reports the geometric truth; warning or blocking is the CALLER's job. A point lying EXACTLY ON AN EDGE counts as INSIDE (Covers, not Contains): a farmer standing on the field's edge must not be wrongly flagged. 422 only when the coordinates are outside the valid range. Do not call without GPS. This is the INTERIM STEP — the goal is a LOCAL check on the device via the offline bundle `GET /gis/sync/parcels` (already available), because losing signal is exactly when people are in the middle of the field.
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
lat | int | query | no | — |
lng | int | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/parcels/<id>/contains-point" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"inside": true,
"parcel_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001"
}/api/v1/gis/parcels/{id}/historyParcel change history
Audit trail of every change (created/boundary-updated/owner-changed/crop-type-changed/status-changed/deleted). Sorted newest first.
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
page | int | query | no | — |
pageSize | int | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/parcels/<id>/history" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"items": [
{
"change_type": "…",
"changed_at": "2026-10-28T07:30:00Z",
"changed_by": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"new_boundary_geo_json": "…",
"notes": "…",
"old_boundary_geo_json": "…",
"parcel_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001"
}
],
"page": 1,
"page_size": 1,
"page_size_capped": true,
"total": 1
}/api/v1/gis/parcels/{parcelId}/photosList photos of a parcel
Returns the photo list with presigned GET URLs (TTL 1 hour).
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
parcelId | GUID | path | yes | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/parcels/<parcelId>/photos" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
[
{
"content_type": "…",
"created_at": "2026-10-28T07:30:00Z",
"file_name": "…",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"size_bytes": 1,
"url": "…"
}
]/api/v1/gis/plotsList plots of a parcel
Returns the plots (Plot) belonging to parcel_id, with crop name, crop group (for the FE to decide dot rendering), plant count + estimated density, and boundary GeoJSON.
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
parcel_id | GUID | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/plots" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
[
{
"area_m2": 1.5,
"boundary_geo_json": "…",
"created_at": "2026-10-28T07:30:00Z",
"crop_category": "…",
"crop_type_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"crop_type_name": "…",
"crops": [
{
"crop_category": "…",
"crop_type_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"crop_type_name": "…",
"estimated_tree_count": 1,
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"note": "…",
"plot_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"role": "…",
"row_spacing_m": 1.5,
"tree_spacing_m": 1.5
}
],
"custom_trees_geo_json": "…",
"density_per1000_m2": 1.5,
"estimated_tree_count": 1,
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"name": "…",
"parcel_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"row_spacing_m": 1.5,
"tree_spacing_m": 1.5
}
]/api/v1/gis/plots/{id}/cropsSpecies planted in the plot (intercropping)
The main species comes first (role = main, matching the plot's crop_type_id). Roles: main · intercrop · shade · border · temporary.
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/plots/<id>/crops" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
[
{
"crop_category": "…",
"crop_type_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"crop_type_name": "…",
"estimated_tree_count": 1,
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"note": "…",
"plot_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"role": "…",
"row_spacing_m": 1.5,
"tree_spacing_m": 1.5
}
]/api/v1/gis/searchSearch parcels, seasons, farmers, zones
Accent-insensitive ("ca phe" matches "Cà phê"). Fewer than 2 characters returns empty. Each group has at most `limit` (1–20, default 8), filtered by permissions + allowed zones.
Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
q | string | query | no | — |
limit | int | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/search" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"farmers": [
{
"code": "…",
"edit_path": "…",
"email": "…",
"id": "…",
"path": "…",
"phone": "…",
"subtitle": "…",
"title": "…",
"type": "…"
}
],
"parcels": [
{
"code": "…",
"edit_path": "…",
"email": "…",
"id": "…",
"path": "…",
"phone": "…",
"subtitle": "…",
"title": "…",
"type": "…"
}
],
"seasons": [
{
"code": "…",
"edit_path": "…",
"email": "…",
"id": "…",
"path": "…",
"phone": "…",
"subtitle": "…",
"title": "…",
"type": "…"
}
],
"zones": [
{
"code": "…",
"edit_path": "…",
"email": "…",
"id": "…",
"path": "…",
"phone": "…",
"subtitle": "…",
"title": "…",
"type": "…"
}
]
}/api/v1/gis/season-templatesList process templates
With `cropTypeId` ⇒ templates for that crop + shared templates (not tied to a crop).
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
cropTypeId | GUID | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/season-templates" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
[
{
"crop_type_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"description": "…",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"name": "…",
"rules": [
{
"age_from": 1,
"age_to": 1,
"anchor": "…",
"day": 1,
"day_offset": 1,
"doses": [
{
"age_from": null,
"age_to": null,
"quantity_per_tree": null
}
],
"event": "…",
"every_days": 1,
"from_day": 1,
"from_month": 1,
"key": "…",
"material": "…",
"month": 1,
"note": "…",
"offset_days": 1,
"task_type": "…",
"title": "…",
"to_day": 1,
"to_month": 1,
"unit": "…"
}
],
"stages": [
{
"day_offset": 1,
"name": "…"
}
],
"updated_at": "2026-10-28T07:30:00Z"
}
]/api/v1/gis/season-templates/{id}Get a process template
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/season-templates/<id>" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"crop_type_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"description": "…",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"name": "…",
"rules": [
{
"age_from": 1,
"age_to": 1,
"anchor": "…",
"day": 1,
"day_offset": 1,
"doses": [
{
"age_from": 1,
"age_to": 1,
"quantity_per_tree": 1.5
}
],
"event": "…",
"every_days": 1,
"from_day": 1,
"from_month": 1,
"key": "…",
"material": "…",
"month": 1,
"note": "…",
"offset_days": 1,
"task_type": "…",
"title": "…",
"to_day": 1,
"to_month": 1,
"unit": "…"
}
],
"stages": [
{
"day_offset": 1,
"name": "…"
}
],
"updated_at": "2026-10-28T07:30:00Z"
}/api/v1/gis/seasonsList seasons
At least one of the two is required: `parcelId` (cultivation history of one parcel) or `year` (12-month bar). With `year`, a season is included if it **TOUCHES** that year — a season planted 12/2025 and harvested 03/2026 appears in both years; otherwise January–February 2026 would look as if there were no season while crops are actually in the field.
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
parcelId | GUID | query | no | — |
year | int | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/seasons" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
[
{
"branch_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"closed_on": "2026-10-28",
"crop_name": "…",
"crop_type_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"expected_harvest_on": "2026-10-28",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"kind": "…",
"name": "…",
"notes": "…",
"parcel_code": "…",
"parcel_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"planted_on": "2026-10-28",
"plot_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"stages": [
{
"day_offset": 1,
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"name": "…",
"sort_order": 1
}
],
"status": "…",
"year": 1,
"yield_kg": 1.5
}
]/api/v1/gis/seasons/groupsSeason groups of a year (same crop, same season name)
Used for the per-season target screen: "Rice · Winter–Spring 2026–27" across many parcels is ONE group. Group key = <crop_type_id>|<season name>|<year>. `branchId` filters seasons on parcels of one farm.
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
year | int | query | no | — |
branchId | GUID | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/seasons/groups" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
[
{
"branch_ids": [
"0190a3c2-5b1e-7c3d-8e4f-000000000001"
],
"crop_name": "…",
"crop_type_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"end_date": "2026-10-28",
"key": "…",
"missing_end_count": 1,
"name": "…",
"parcel_count": 1,
"season_count": 1,
"start_date": "2026-10-28",
"year": 1
}
]/api/v1/gis/seasons/{id}Get a season by ID
Used by `nextfarm-harvest`: when declaring a harvest it needs to know WHAT CROP the season grows and WHETHER IT IS CLOSED; when building the traceability page it needs the season name + planting date + expected harvest date to print on the label.
gis.parcels.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/seasons/<id>" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"branch_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"closed_on": "2026-10-28",
"crop_name": "…",
"crop_type_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"expected_harvest_on": "2026-10-28",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"kind": "…",
"name": "…",
"notes": "…",
"parcel_code": "…",
"parcel_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"planted_on": "2026-10-28",
"plot_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"stages": [
{
"day_offset": 1,
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"name": "…",
"sort_order": 1
}
],
"status": "…",
"year": 1,
"yield_kg": 1.5
}/api/v1/gis/zonesDanh sách zones
Filter by zone_type (province/district/commune/material_zone). Paginated.
gis.zones.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
zone_type | string | query | no | — |
page | int | query | no | — |
page_size | int | query | no | — |
deleted | bool | query | no | — |
include_stats | bool | query | no | — |
branch_id | GUID | query | no | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/zones?page_size=20" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"items": [
{
"branch_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"code": "…",
"contact_person": "…",
"contact_phone": "…",
"description": "…",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"implausible_parcel_count": 1,
"main_crop": "…",
"name": "…",
"parcel_area_ha": 1.5,
"parcel_count": 1,
"parent_zone_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"total_area_ha": 1.5,
"zone_type": "…"
}
],
"page": 1,
"page_size": 1,
"page_size_capped": true,
"total": 1
}/api/v1/gis/zones/{id}Get a zone
Returns full details + parent zone name + boundary GeoJSON.
gis.zones.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/zones/<id>" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"boundary_geo_json": "…",
"branch_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"code": "…",
"contact_person": "…",
"contact_phone": "…",
"created_at": "2026-10-28T07:30:00Z",
"description": "…",
"id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"main_crop": "…",
"name": "…",
"parent_zone_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"parent_zone_name": "…",
"total_area_ha": 1.5,
"updated_at": "2026-10-28T07:30:00Z",
"zone_type": "…"
}/api/v1/gis/zones/{id}/statsZone statistics
Number of parcels + total area belonging to the current workspace in this zone.
gis.zones.viewTry in API Explorer ▶Parameter
| Parameter | Type | In | Required | Description |
|---|---|---|---|---|
id | GUID | path | yes | — |
Example
curl -X GET "https://api-prod.nextfarm.vn/api/v1/gis/zones/<id>/stats" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Sample response
200 OK
{
"active_parcel_count": 1,
"disputed_parcel_count": 1,
"excluded_area_ha": 1.5,
"implausible_parcel_count": 1,
"inactive_parcel_count": 1,
"parcel_count": 1,
"total_area_ha": 1.5,
"zone_id": "0190a3c2-5b1e-7c3d-8e4f-000000000001",
"zone_name": "…"
}