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:
- Typescript
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}`,
},
}
);
{
"id": "78b1045a-a65d-4c51-915b-4ad9dac94da0",
"name": "Alice Farm",
"address": "Phanthai Norasing, Mueang Samut Sakhon District, Samut Sakhon 74000, Thailand",
"phone": "+661234567892"
}
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.
- Typescript
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}`,
},
}
);
{
"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.
- Typescript
import axios from "axios";
axios.get("https://agro.api.listenfield.com/crops?page=1", {
headers: {
Authorization: `Bearer {YOUR_API_TOKEN}`,
},
});
[
{
"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"
}
}
...
]
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
- Typescript
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}`,
},
}
);
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.
{
"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
}
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
- Typescript
import axios from "axios";
axios.get("https://agro.api.listenfield.com/activity_types?page=1", {
headers: {
Authorization: `Bearer {YOUR_API_TOKEN}`,
},
});
[
{
"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.
- Typescript
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}`,
},
}
);
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.
{
"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"
}
}