Skip to main content

Full Journey

In this tutorial we are gonna through a full journey of the basic farm management features of the AgroAPI.
We will create a farm for Alice, with a field in it, and 2 cropzones. We will then create an activity in each cropzone!

An AgroAPI token is required. If you don't have a token yet please contact support@listenfield.com.

Note: The code/samples presented here are subject to change. Always check the Api Docs tab which is the most up to date.

Creating Farms

Let's start with creating a farm for Alice.
You can call the create farm endpoint:

import axios from "axios";

axios.post(
"https://agro.api.listenfield.com/farms",
{
name: "Alice Farm",
phone: "+661234567890",
address:
"Phanthai Norasing, Mueang Samut Sakhon District, Samut Sakhon 74000, Thailand",
},
{
headers: {
Authorization: `Bearer {YOUR_API_TOKEN}`,
},
}
);
API Response
{
"id": "78b1045a-a65d-4c51-915b-4ad9dac94da0",
"name": "Alice Farm",
"address": "Phanthai Norasing, Mueang Samut Sakhon District, Samut Sakhon 74000, Thailand",
"phone": "+661234567892"
}
caution

The format of coordinates is [longitude, latitude] and NOT [latitude, longitude].

Then, now you could save in your personal backend something like:

User {
email: 'alice@alice.com'
farms: [78b1045a-a65d-4c51-915b-4ad9dac94da0]
}

Creating Fields

Then, let's say you want to add fields into the farm we just created (id 78b1045a-a65d-4c51-915b-4ad9dac94da0).
You can use the create field endpoint.

import axios from "axios";

axios.post(
"https://agro.api.listenfield.com/farms/78b1045a-a65d-4c51-915b-4ad9dac94da0/fields",
{
name: "Alice First field",
location: {
type: "Polygon",
coordinates: [
[
[100.4612159729004, 13.82024460030749],
[100.46422004699708, 13.82032794617722],
[100.4634475708008, 13.82266161842019],
[100.4612159729004, 13.82024460030749],
],
],
},
},
{
headers: {
Authorization: `Bearer {YOUR_API_TOKEN}`,
},
}
);
API Response
{
"id": "0c261330-44e3-45cf-b80a-d2ef4471d568",
"farm_id": "78b1045a-a65d-4c51-915b-4ad9dac94da0",
"name": "Alice First field",
"area": 45143,
"location": {
"centroid": {
"type": "Point",
"coordinates": [
100.46296034084827,
13.821077937178746
]
},
"boundary": {
"type": "Polygon",
"coordinates": [
[
[
100.4612159729004,
13.82024460030749
],
[
100.46422004699708,
13.82032794617722
],
[
100.4634475708008,
13.82266161842019
],
[
100.4612159729004,
13.82024460030749
]
]
]
}
},
"crops_summary": [],
"preview_uri": "https://maps.googleapis.com/maps/api/staticmap?center=13.82107793717874....."
}

As you can see in the response, the area size has been automatically computed from the geojson polygon you provided.
The centroid (center of the field) is also pre-computed from the polygon.
You are also getting the field UUID that you can now save in your database for easier access later (you can always use the field index endpoint too)

Creating Cropzones

Inside a same field it's common to plant multiple different crops. This concept is implemented with Cropzones.

First, in order to create a Cropzone, we need to get a Crop ID.
We can call the /crops endpoint to know the list of supported crops.
The /crops endpoint is paginated (e.g ?page=1 in the URL) as we have many supported crops.

import axios from "axios";

axios.get("https://agro.api.listenfield.com/crops?page=1", {
headers: {
Authorization: `Bearer {YOUR_API_TOKEN}`,
},
});
API Response
[
{
"id": "0052326a-5023-41a5-86b1-e24a9afdf21d",
"name": "potato",
"canonical_name": "potato_atlantic",
"variety": "Atlantic",
"genus": "Solanum spp.",
"name_i18n": {
"en": "potato",
"ja": "じゃがいも",
"th": "มันฝรั่ง",
"vi": "khoai tây"
},
"variety_i18n": {
"en": "Atlantic",
"ja": "Atlantic",
"th": "แอตแลนติก",
"vi": "Atlantic"
}
},
{
"id": "014301b2-3e17-4983-b382-f6478df393fe",
"name": "bell pepper",
"canonical_name": "bell_pepper_generic",
"variety": "generic",
"genus": "Capsicum spp.",
"name_i18n": {
"en": "bell pepper",
"ja": "ピーマン",
"th": "พริกหยวก",
"vi": "Ớt chuông"
},
"variety_i18n": {
"en": "Generic",
"ja": "一般",
"th": "ทั่วไป",
"vi": "Khác"
}
},
{
"id": "0178863e-419f-4932-92fc-260dbea8d7ea",
"name": "rice",
"canonical_name": "rice_akidawara",
"variety": "Akidawara",
"genus": "Oryzae spp.",
"name_i18n": {
"en": "rice",
"ja": "米",
"th": "ข้าว",
"vi": "gạo"
},
"variety_i18n": {
"en": "Akidawara",
"ja": "Akidawara",
"th": "อะกิดะวะระ",
"vi": "Akidawara"
}
},
{
"id": "04382051-da4b-4371-806a-7b4b5ed891f9",
"name": "garlic chives",
"canonical_name": "garlic_chives_generic",
"variety": "generic",
"genus": "Allium spp.",
"name_i18n": {
"en": "Garlic chives",
"ja": "garlic chives",
"th": "กุ้ยช่าย",
"vi": "garlic chives"
},
"variety_i18n": {
"en": "Generic",
"ja": "generic",
"th": "ทั่วไป",
"vi": "generic"
}
},
{
"id": "0460a2fb-9c34-40e1-8a3d-b2a540b86b1c",
"name": "rice",
"canonical_name": "rice_Aichi_No_Kaori",
"variety": "Aichi No Kaori",
"genus": "Oryzae spp.",
"name_i18n": {
"en": "rice",
"ja": "米",
"th": "ข้าว",
"vi": "gạo"
},
"variety_i18n": {
"en": "Aichi No Kaori",
"ja": "あいちのかお",
"th": "พันธุ์อิชิโนะคาโอริ",
"vi": "gạo Aichi No Kaori"
}
}
...
]
info

Each crop has a canonical_name, this name is unique and used as a unique key to recognize the [crop,variety] combination instead of the ID in some cases where you expect the backend ID to change (like between a staging server and a production server of the AgroAPI, this is likely not a problem for you and it's recommend to use the ID instead).

Now that we got some crops, let's create a cropzone into our previously created Field (0c261330-44e3-45cf-b80a-d2ef4471d568). We'll create a banana cropzone over half of the field area.
Create Cropzone Endpoint

import axios from "axios";

axios.post(
"https://agro.api.listenfield.com/fields/0c261330-44e3-45cf-b80a-d2ef4471d568/cropzones",
{
name: "Banana cropzone",
planting_date: "2021-04-29T11:36:00.000Z",
crop_id: "22c2d1d3-c413-468a-be6f-e2bc5d31d1b5",
},
{
headers: {
Authorization: `Bearer {YOUR_API_TOKEN}`,
},
}
);
info

planting_date is the planting date of the cropzone. A planting activity will be automatically created at this date.
A cropzone can also be archived after harvesting with the archive endpoint. The end_date of a cropzone will always mirror the latest harvesting date.

API Response
{
"id": "0e8fdf97-1e0b-4d3e-9dc3-2dbe2244fc19",
"name": "Banana cropzone",
"area": 42,
"start_date": "2021-04-29T11:36:00.000Z",
"end_date": "2022-04-29T11:36:00.000Z",
"crop": {
"id": "0c66a6f8-ad0d-4648-829c-a378d4ba5749",
"name": "banana",
"canonical_name": "banana_ducasse",
"variety": "Ducasse",
"genus": "Musa spp.",
"name_i18n": {
"en": "banana",
"ja": "バナナ",
"th": "กล้วย",
"vi": "chuối"
},
"variety_i18n": {
"en": "Ducasse",
"ja": "Ducasse",
"th": "กล้วยนํ้าหว้า",
"vi": "Ducasse"
}
},
"field_id": "0c261330-44e3-45cf-b80a-d2ef4471d568",
"activities_count": 1
}
info

Cropzones can also have polygons defined, the same way as fields. By default, if the polygon is not defined the field polygon will be automatically inherited.

Creating Activities

Inside a cropzone it is possible to create activities.
Each activity has an ActivityType.
You can get the list of ActivityTypes by calling the List Activity Types endpoint

import axios from "axios";

axios.get("https://agro.api.listenfield.com/activity_types?page=1", {
headers: {
Authorization: `Bearer {YOUR_API_TOKEN}`,
},
});
API Response
[
{
"id": "8be03dd7-4c8b-4b76-aaff-9efb45ab4100",
"name": "Weed Control",
"canonical_name": "weed_control",
},
{
"id": "c15630fa-b3be-4134-8cf6-a88dfdd1a120",
"name": "Monitoring",
"canonical_name": "monitoring",
},
{
"id": "0011f27e-b1fa-491f-90ec-3d6f03abeb7b",
"name": "Inspection",
"canonical_name": "inspection",
},
{
"id": "6da3d978-b60d-498a-9166-33bf5bff00c2",
"name": "Producing Fertilizer",
"canonical_name": "producing_fertilizer",
},
{
"id": "4c69471f-f0f9-46f1-88d7-15426bc59af1",
"name": "Other",
"canonical_name": "other",
},
{
"id": "e4c1ec8a-efa4-4f68-8eeb-6c0d23c36841",
"name": "Land Preparation",
"canonical_name": "land_preparation",
}
]

Now that we got some activity types, you can create the activity by calling the Create Activity endpoint.

import axios from "axios";

axios.post(
"https://agro.api.listenfield.com/cropzones/0e8fdf97-1e0b-4d3e-9dc3-2dbe2244fc19/activities",
{
activity_type_id: "e4c1ec8a-efa4-4f68-8eeb-6c0d23c36841",
start_date: "2021-04-29T11:36:00.000Z",
extra: {},
},
{
headers: {
Authorization: `Bearer {YOUR_API_TOKEN}`,
},
}
);
info

Each activity has a extra field where you can store custom information related to the Activity in some special cases. Like harvesting activities, planting activities, and soil observation activities.

API Response
{
"id": "19985969-e8b0-4e29-8f5d-461ec352c99e",
"status": "default",
"activity_extra": {
"equipment": true
},
"activity_type": {
"id": "e4c1ec8a-efa4-4f68-8eeb-6c0d23c36841",
"name": "Land Preparation",
"canonical_name": "land_preparation",
"technique": null,
"extra": {
"equipment": true
},
"description": null,
"crops": [],
"observational": null
},
"type": "CropzoneActivity",
"start_date": "2021-05-06T12:39:36.000Z",
"end_date": "2021-07-16T10:20:11.000Z",
"attachments": [],
"note": null,
"cropzone_id": "0e8fdf97-1e0b-4d3e-9dc3-2dbe2244fc19",
"cropzone": {
"id": "0e8fdf97-1e0b-4d3e-9dc3-2dbe2244fc19",
"name": "Banana cropzone",
"area": 42,
"start_date": "2021-04-29T11:36:00.000Z",
"end_date": "2021-04-29T11:36:00.000Z",
"crop": {
"id": "22c2d1d3-c413-468a-be6f-e2bc5d31d1b5",
"name": "banana",
"canonical_name": "banana",
"variety": "generic"
},
"field_id": "0c261330-44e3-45cf-b80a-d2ef4471d568",
"activities_count": 2
},
"farm": {
"id": "78b1045a-a65d-4c51-915b-4ad9dac94da0",
"name": "Alice Farm",
"email": null,
"address": "Phanthai Norasing, Mueang Samut Sakhon District, Samut Sakhon 74000, Thailand",
"phone": "+661234567892",
"description": null,
"avatar": null,
"location": {
"type": "Point",
"coordinates": [
100.3785204,
13.5332364
]
},
"preview_uri": "https://maps.googleapis.com/maps/api/staticmap?center=13.5332364,100.3785204"
},
"field": {
"id": "0c261330-44e3-45cf-b80a-d2ef4471d568",
"farm_id": "78b1045a-a65d-4c51-915b-4ad9dac94da0",
"name": "Alice First field",
"area": 45143,
"location": {
"centroid": {
"type": "Point",
"coordinates": [
100.46296034084827,
13.821077937178746
]
},
"boundary": {
"type": "Polygon",
"coordinates": [
[
[
100.4612159729004,
13.82024460030749
],
[
100.46422004699708,
13.82032794617722
],
[
100.4634475708008,
13.82266161842019
],
[
100.4612159729004,
13.82024460030749
]
]
]
}
},
"crops_summary": [
{
"id": "22c2d1d3-c413-468a-be6f-e2bc5d31d1b5",
"name": "banana",
"canonical_name": "banana",
"variety": "generic"
}
],
"preview_uri": "https://maps.googleapis.com/maps/api/staticmap?center=13.821077937178746,100.4629603408482"
}
}