NDVI API
The normalized difference vegetation index (NDVI) is a simple graphical indicator that can be used to analyze remote sensing measurements, often from a space platform, assessing whether the target being observed contains live green vegetation. Wikipedia
Search NDVI
GET /v1/ndvi/search
Request parameters
| Name | Type | Description |
|---|---|---|
| geometry_wkt | String | Geometry representation in WKT format |
| datetime | String | String represented date in format ISO-8601 |
| limit | Integer | (Optional) Number of results per page (Default: 50) |
| min_tile_cloudiness | Integer | (Optional) Minimal cloudiness calculated by tile (internally is used 100x100 km tiles) |
| max_tile_cloudiness | Integer | (Optional) Maximal cloudiness calculated by tile (internally is used 100x100 km tiles) |
| order | String | (Optional) Sorting direction asc or desc |
| remove_duplicates | Boolean | (Optional) Choosing only one item per day (based on cloudiness and data coverage) |
Coordinate ordering
In accordance with RFC 7946, Section 3.1.1, coordinates must follow the specified order: longitude first, followed by latitude.
remove_duplicates
Due to the specifics of the orbits and coverage of the Sentinel-2 satellite, there can be several images for one date. Setting this parameter to true filters the images to select the one with the lowest cloudiness and highest data coverage, returning only one per date.
datetime
Either a single datetime or datetime range used to filter results. You may express a single datetime using a RFC 3339-compliant timestamp, or a simple date string (see below). Timezone aware instances will be converted to a UTC timestamp before being passed to the endpoint. Timezone unaware instances are assumed to represent UTC timestamps.
You may represent a datetime range using a "/" separated string as described in the spec, or a list, tuple,
or iterator of 2 timestamps or datetime instances.
For open-ended ranges, use either ".." ('2020-01-01:00:00:00Z/..', ['2020-01-01:00:00:00Z', '..'])
or a value of None (['2020-01-01:00:00:00Z', None]).
If using a simple date string, the datetime can be specified in YYYY-mm-dd format, optionally truncating to YYYY-mm or just YYYY. Simple date strings will be expanded to include the entire time period, for example:
2017expands to2017-01-01T00:00:00Z/2017-12-31T23:59:59Z2017-06expands to2017-06-01T00:00:00Z/2017-06-30T23:59:59Z2017-06-10expands to2017-06-10T00:00:00Z/2017-06-10T23:59:59Z
If used in a range, the end of the range expands to the end of that day/month/year, for example:
2017/2018expands to2017-01-01T00:00:00Z/2018-12-31T23:59:59Z2017-06/2017-07expands to2017-06-01T00:00:00Z/2017-07-31T23:59:59Z2017-06-10/2017-06-11expands to2017-06-10T00:00:00Z/2017-06-11T23:59:59Z
geometry limitations
- Supports only
PolygonandMultiPolygongeometry - Minimal allowed area for geometry is 0,01 ha
- Maximal allowed area for geometry is 1.000 ha
Response parameters
In the results returns list of available items for given region, each item contains following parameters:
| Name | Type | Description |
|---|---|---|
| id | String | Unique identifier of data |
| datetime | String | String represented date in format ISO-8601 |
| tile_id | String | Unique identifie of tile within MGRS grid |
| tile_cloudiness | Float | Cloud coverage for tile |
| tile_nodata | Float | No-data coverage for tile |
Example:
export ONESOIL_API_TOKEN=<YOUR TOKEN>
export ONESOIL_API_HOST=https://api-b2b.prod-be.onesoil.ai
curl -H "Authorization: Bearer ${ONESOIL_API_TOKEN}" "${ONESOIL_API_HOST}/v1/ndvi/search?geometry_wkt=POLYGON%20((6.771993234816421%2052.336449417960665%2C%206.771993234816421%2052.330602089755615%2C%206.783012191002371%2052.330602089755615%2C%206.783012191002371%2052.336449417960665%2C%206.771993234816421%2052.336449417960665))&datetime=2023-02-01%2F2023-03-01&order=asc&remove_duplicates=true" \
{
"result": [
{
"id": "S2A_31UGU_20230201_0_L2A",
"datetime": "2023-02-01T10:46:21.031000+00:00",
"tile_id": "31UGU",
"tile_cloudiness": 99.531639,
"tile_nodata": 0.0
},
{
"id": "S2A_31UGU_20230204_0_L2A",
"datetime": "2023-02-04T10:56:17.644000+00:00",
"tile_id": "31UGU",
"tile_cloudiness": 54.327613,
"tile_nodata": 33.38412
},
...
],
"meta": {
"limit": 50,
"total": 24
}
}
NDVI Info
GET /v1/ndvi/info/{item_id}
where item_id is the id of item from the Search NDVI response.
Request parameters:
| Name | Type | Description |
|---|---|---|
| geometry_wkt | String | Geometry representation in WKT format |
Response example:
{
"datetime": "2023-02-01T10:46:21.031000+00:00",
"statistics": {
"min": 0.3615686893463135,
"max": 0.8015686869621277,
"mean": 0.6733093857765198,
"std": 0.09569674730300903,
"p25": 0.6117647290229797,
"p50": 0.7066666483879089,
"p75": 0.7541177272796631,
"p90": 0.7670589089393616
},
"histogram": {
"values": [
25,
50,
71,
49,
145,
236,
197,
296,
493,
433
],
"bins": [
0.3615687,
0.4055687,
0.4495687,
0.4935687,
0.5375687,
0.5815687,
0.6255687,
0.66956866,
0.7135687,
0.7575687,
0.8015687
]
},
"cloud_coverage": 2.778,
"area": 178294.7329040179
}
Where histogram contains amount of values for each bin
NDVI Image
GET /v1/ndvi/images/{item_id}
where item_id is the id of item from the Search NDVI response.
Request parameters
| Name | Type | Description |
|---|---|---|
| geometry_wkt | String | Geometry representation in WKT format |
| format | String | png or tiff |
| resolution | Integer | Resolution m/px, any integer value from range 2..10 (Default: 10) |
| palette | String | Name of palette for colorization, see possible values below (Default: brown-green) |
| nocache | Boolean | Don't use cache and run calculate from scratch (Default: false) |
Warning
For correct getting image you must specify Accept header with corresponding format that you are using. In otherwise you get binary data encoded in base64.
The output is provided as an RGBA (Red, Green, Blue, Alpha) 8-bit encoded image. The alpha channel uses the following values to represent different areas:
- 0: Area outside the field.
- 128: Areas covered by clouds.
- 255: Valid field area.
Example of request
export ONESOIL_API_TOKEN=<YOUR TOKEN>
export ONESOIL_API_HOST=https://api-b2b.prod-be.onesoil.ai
curl --request GET \
--url '${ONESOIL_API_HOST}/v1/ndvi/images/S2A_31UGU_20200629_0_L2A?geometry_wkt=POLYGON((1.1529353383469356 48.74173886632221, 1.1496963460259337 48.741708782269285, 1.1457730595526812 48.740264726546826, 1.1487991603596583 48.73715585468403, 1.1489816387995688 48.73638362121744, 1.1545168181653764 48.7368650149009, 1.1529353383469356 48.74173886632221))&palette=contrasted&resolution=5&format=png' \
--header 'accept: image/png' \
--header 'authorization: Bearer ${ONESOIL_API_TOKEN}'
let wellknown = require('wellknown');
const ONESOIL_API_TOKEN = "<YOUR TOKEN>";
const ONESOIL_API_HOST = "https://api-b2b.prod-be.onesoil.ai";
let query = new URLSearchParams({
geometry_wkt: wellknown.stringify({
"type": "Polygon",
"coordinates": [
[
[ 1.1529353383469356, 48.741738866322208 ],
[ 1.1496963460259337, 48.741708782269285 ],
[ 1.1457730595526812, 48.740264726546826 ],
[ 1.1487991603596583, 48.737155854684033 ],
[ 1.1489816387995688, 48.736383621217442 ],
[ 1.1545168181653764, 48.736865014900900 ],
[ 1.1529353383469356, 48.741738866322208 ]
]
]
}),
resolution: 5,
palette: "contrasted",
format: "png"
});
response = await fetch(
`${ONESOIL_API_HOST}/v1/ndvi/images/S2B_31UFS_20200601_0_L2A?${query.toString()}`,
{
headers: {
"Accept": "image/png",
"Authorization": `Bearer ${ONESOIL_API_TOKEN}`
}
}
);
console.assert(response.status, 200);
console.assert(response.headers.get('content-type'), "image/png");
const blob = await response.blob();
const url = URL.createObjectURL(blob);
const img = document.createElement('img');
img.src = url;
import requests
from shapely.geometry import shape
from shapely.wkt import dumps as wkt_dumps
ONESOIL_API_TOKEN = "<YOUR TOKEN>
ONESOIL_API_HOST = "https://api-b2b.prod-be.onesoil.ai"
response = requests.get(
f"{ONESOIL_API_HOST}/v1/ndvi/images/S2B_31UFS_20200601_0_L2A",
params={
"geometry_wkt": wkt_dumps(shape({
"type": "Polygon",
"coordinates": [
[
[ 1.1529353383469356, 48.741738866322208 ],
[ 1.1496963460259337, 48.741708782269285 ],
[ 1.1457730595526812, 48.740264726546826 ],
[ 1.1487991603596583, 48.737155854684033 ],
[ 1.1489816387995688, 48.736383621217442 ],
[ 1.1545168181653764, 48.736865014900900 ],
[ 1.1529353383469356, 48.741738866322208 ]
]
]
})),
"format": "png"
},
headers={
"Accept": "image/png",
"Authorization": f"Bearer {ONESOIL_API_TOKEN}"
}
)
assert response.status_code == 200
assert response.headers["Content-Type"] == "image/png"
Example of output

Palettes
grayscale
Image with values increase gradually from 1 to 255, the corresponding NDVI values rise from 0.01 to 1.0.
red-green
| NDVI range | Hex color | Color |
|---|---|---|
| ... ≤ 0.0 | #a50026 | |
| 0.0 < ... ≤ 0.1 | #d73027 | |
| 0.1 < ... ≤ 0.2 | #f46d43 | |
| 0.2 < ... ≤ 0.3 | #fdae61 | |
| 0.3 < ... ≤ 0.4 | #fee08b | |
| 0.4 < ... ≤ 0.5 | #ffffbf | |
| 0.5 < ... ≤ 0.6 | #d9ef8b | |
| 0.6 < ... ≤ 0.7 | #a6d96a | |
| 0.7 < ... ≤ 0.8 | #66bd63 | |
| 0.8 < ... ≤ 0.9 | #1a9850 | |
| 0.9 < ... ≤ 1.0 | #006837 |
brown-green
| NDVI range | Hex color | Color |
|---|---|---|
| ... < 0.00 | #000000 | |
| 0.00 < ... ≤ 0.05 | #422112 | |
| 0.05 < ... ≤ 0.10 | #7f4020 | |
| 0.1 < ... ≤ 0.15 | #b76135 | |
| 0.15 < ... ≤ 0.20 | #c6974e | |
| 0.20 < ... ≤ 0.25 | #e6c957 | |
| 0.25 < ... ≤ 0.30 | #fdfe03 | |
| 0.30 < ... ≤ 0.35 | #e6ec06 | |
| 0.35 < ... ≤ 0.40 | #d0df00 | |
| 0.40 < ... ≤ 0.45 | #b9cf02 | |
| 0.45 < ... ≤ 0.50 | #a2c000 | |
| 0.50 < ... ≤ 0.55 | #8aaf00 | |
| 0.55 < ... ≤ 0.60 | #72a000 | |
| 0.60 < ... ≤ 0.65 | #5b8e03 | |
| 0.65 < ... ≤ 0.70 | #458100 | |
| 0.70 < ... ≤ 0.75 | #2d7000 | |
| 0.75 < ... ≤ 0.80 | #25602d | |
| 0.85 < ... ≤ 1.00 | #15542d |
contrasted
Note
For this palette, colorization is done from the min to the max values of a particular image. In the metadata of the image, you can find the palette with values that are used.
| Hex color | Color |
|---|---|
| #960850 | |
| #EE0200 | |
| #ff771c | |
| #ffbd38 | |
| #feff03 | |
| #bdf100 | |
| #3fe10e | |
| #07b55e | |
| #0b8877 |