Skip to content

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:

  • 2017 expands to 2017-01-01T00:00:00Z/2017-12-31T23:59:59Z
  • 2017-06 expands to 2017-06-01T00:00:00Z/2017-06-30T23:59:59Z
  • 2017-06-10 expands to 2017-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/2018 expands to 2017-01-01T00:00:00Z/2018-12-31T23:59:59Z
  • 2017-06/2017-07 expands to 2017-06-01T00:00:00Z/2017-07-31T23:59:59Z
  • 2017-06-10/2017-06-11 expands to 2017-06-10T00:00:00Z/2017-06-11T23:59:59Z

geometry limitations

  • Supports only Polygon and MultiPolygon geometry
  • 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

Demo

Open NDVI-demo