Examples of Third Party Data Import

The first example below demonstrates the import of PlanetScope data and the second one the import of Pleiades data. We included the examples of both Simple and Native search so that you can compare their interfaces even though both would usually not be used in the same workflow. Similar applies for the examples of Order products and of Order using query. The requests are given in Python. To execute them you need to create an OAuth client as is explained here. It is named oauth in these examples.

A Postman collection with examples can be downloaded here. You will need a SH access token to run the examples successfully.

For more detailed explanations, follow our step by step tutorial on ordering and visualizing commercial data using Postman.

Get your quota

url = "https://services.sentinel-hub.com/api/v1/dataimport/quotas"
response = oauth.get(url=url)
response.raise_for_status()
response.json()

PlanetScope data import

The examples below use the PSScene itemType with the 8-band analytic_8b_sr_udm2 bundle. If you're interested in PlanetScope data before 2018, use a 4-band bundle (analytic_sr_udm2 or analytic_udm2) instead. Additionally, note that different item types and bundles aren't compatible, so you cannot mix them in the same BYOC collection.

For PlanetScope simple search, provider must be set to "PLANET". We suggest to set the data.itemType to "PSScene" (read about the options here.).

url = "https://services.sentinel-hub.com/api/v1/dataimport/search"
query = {
"provider": "PLANET",
"bounds": {
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
15.825815,
46.714048
],
[
15.813988,
46.707248
],
[
15.832682,
46.703062
],
[
15.839931,
46.711694
],
[
15.835353,
46.716664
],
[
15.825815,
46.714048
]
]
]
}
},
"data": [
{
"itemType": "PSScene",
"dataFilter": {
"timeRange": {
"from": "2019-04-27T00:00:00.000Z",
"to": "2019-04-30T00:00:00.000Z"
},
"maxCloudCoverage": 30,
"nativeFilter": {
"type": "StringInFilter",
"field_name": "quality_category",
"config": [
"standard"
]
}
}
}
]
}
response = oauth.post(url, json=query)
response.raise_for_status()
results = response.json()

To get product ids:

item_ids = [feature["id"] for feature in results["features"]]

This native search is equivalent to the above simple search. Note the added Planet-specific filters PermissionFilter and AssetFilter.

url = "https://services.sentinel-hub.com/api/v1/dataimport/nativesearch"
payload = {
"provider": "PLANET",
"item_types": [
"PSScene"
],
"filter": {
"type": "AndFilter",
"config": [
{
"type": "GeometryFilter",
"field_name": "geometry",
"config": {
"type": "Polygon",
"coordinates": [
[
[
15.825815,
46.714048
],
[
15.813988,
46.707248
],
[
15.832682,
46.703062
],
[
15.839931,
46.711694
],
[
15.835353,
46.716664
],
[
15.825815,
46.714048
]
]
]
}
},
{
"type": "DateRangeFilter",
"field_name": "acquired",
"config": {
"gte": "2019-04-27T00:00:00.000Z",
"lte": "2019-04-30T00:00:00.000Z"
}
},
{
"type": "RangeFilter",
"field_name": "cloud_cover",
"config": {
"lte": 0.3
}
},
{
"type": "StringInFilter",
"field_name": "quality_category",
"config": [
"standard"
]
},
{
"type" : "PermissionFilter",
"config" : [ "assets:download" ]
},
{
"type" : "AssetFilter",
"config" : [ "analytic" ]
}
]
}
}
response = oauth.post(url, json=payload)
response.raise_for_status()
results = response.json()

To get product ids:

item_ids = [feature["id"] for feature in results["features"]]

Thumbnail

After searching for data, you can check the thumbnail of each item by entering the item id into the url of the thumbnail request:

item_id = '20190427_093732_22_105d'
# or get it from search results: item_id = item_ids[0]
url = f"https://services.sentinel-hub.com/api/v1/dataimport/collections/PLANET_SCOPE/products/{item_id}/thumbnail"
response = oauth.get(url)

The thumbnail can be displayed in Python using:

import io
from PIL import Image
image_bytes = io.BytesIO(response.content)
Image.open(image_bytes)

Order

For these demonstrational examples, you do not need to set the input.planetApiKey, as long as you do not modify the input objects of the data orders. To order PlanetScope data, provider must be set to "PLANET" and data.itemType to "PSScene".

Order products

To order the import of the products, which we got as a result of search and are stored in the variable item_ids:

url = "https://services.sentinel-hub.com/api/v1/dataimport/orders"
payload = {
"name": "planet products",
# collectionId is optional. Remove it to create a new collection.
"collectionId": "<your Planet collectionId>",
"input": {
"provider": "PLANET",
"planetApiKey": "", # Insert your Planet api key
"bounds": {
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
15.825815,
46.714048
],
[
15.813988,
46.707248
],
[
15.832682,
46.703062
],
[
15.839931,
46.711694
],
[
15.835353,
46.716664
],
[
15.825815,
46.714048
]
]
]
}
},
"data": [
{
"itemType": "PSScene",
"productBundle": "analytic_8b_sr_udm2",
"itemIds": item_ids
}
]
}
}
response = oauth.post(url, json=payload)
response.raise_for_status()
results = response.json()

Order using query

Another way to order data is using search query, in this case using the query from above:

url = "https://services.sentinel-hub.com/api/v1/dataimport/orders"
query['input']['planetApiKey'] = "" # Insert your Planet api key
query['data'][0]["productBundle"] = "analytic_8b_sr_udm2"
payload = {
"name": "some name",
# collectionId is optional. Remove it to create a new collection.
"collectionId": "<your Planet collectionId>",
"input": query
}
response = oauth.post(url, json=payload)
response.raise_for_status()
order = response.json()

To extract the order id from the response:

order_id = order['id']

To extract the cost in square kilometers:

sqkm = order['sqkm']

Confirm the order

Confirming the order will subtract the ordered area in km2 from your quota. To initiate import, confirm the order:

url = f"https://services.sentinel-hub.com/api/v1/dataimport/orders/{order_id}/confirm"
response = oauth.post(url)
response.raise_for_status()

Get order information

url = f"https://services.sentinel-hub.com/api/v1/dataimport/orders/{order_id}"
response = oauth.get(url)
response.raise_for_status()
order = response.json()

To extract the order status:

status = order['status']

To extract the BYOC collection ID:

collection_id = order['collectionId']

List all your orders

url = "https://services.sentinel-hub.com/api/v1/dataimport/orders"
response = oauth.get(url)
response.raise_for_status()
response.json()

Subscribe

Subscribing to PlanetScope data is similar to ordering using a search query, again starting with the query from simple search.

url = "https://services.sentinel-hub.com/api/v1/dataimport/subscriptions"
query['planetApiKey'] = "" # Insert your Planet api key
query['data'][0]["productBundle"] = "analytic_8b_sr_udm2"
query['data'][0]["harmonizeTo"] = "NONE"
payload = {
"name": "my subscription",
# collectionId is optional. Remove it to create a new collection.
"collectionId": "<your Planet collectionId>",
"input": query
}
response = oauth.post(url, json=payload)
response.raise_for_status()
subscription = response.json()

To extract the subscription id from the response:

subscription_id = subscription['id']

To extract the area in square kilometers:

sqkm = subscription['sqkm']

Confirm the subscription

Confirming the subscription will subtract the subscribed area in km2 from your quota. To initiate import, confirm the subscription:

url = f"https://services.sentinel-hub.com/api/v1/dataimport/subscriptions/{subscription_id}/confirm"
response = oauth.post(url)
response.raise_for_status()

Get subscription information

url = f"https://services.sentinel-hub.com/api/v1/dataimport/subscriptions/{subscription_id}"
response = oauth.get(url)
response.raise_for_status()
subscription = response.json()

To extract the subscription status:

status = subscription['status']

To extract the BYOC collection ID:

collection_id = subscription['collectionId']

List subscription deliveries

To list deliveries created so far for the subscription:

url = f"https://services.sentinel-hub.com/api/v1/dataimport/subscriptions/{subscription_id}/deliveries"
response = oauth.get(url)
response.raise_for_status()
deliveries = response.json()

List all your subscriptions

url = "https://services.sentinel-hub.com/api/v1/dataimport/subscriptions"
response = oauth.get(url)
response.raise_for_status()
response.json()

Access PlanetScope data in a BYOC collection and process a truecolor image

This is a normal Process API request that uses a BYOC collectionId that can be fetched from the get order information request.

response = oauth.post('https://services.sentinel-hub.com/api/v1/process',
headers={"Authorization" : "Bearer <your_access_token>"},
json={
'input': {
"bounds": {
"properties": {
"crs": "http://www.opengis.net/def/crs/EPSG/0/32633"
},
"bbox": [562218,5174019,564201,5172501]
},
"data": [{
"type": "byoc-<collectionId>",
"dataFilter": {
"timeRange": {
"from": "2019-04-27T00:00:00Z",
"to": "2019-04-28T00:00:00Z"
}
}
}
]
},
"output": {
"width": 512,
"height": 512
},
"evalscript": """
//VERSION=3
function setup() {
return {
input: [{"bands": ["B1", "B2", "B3","dataMask"]}],
output: { bands: 4}
};
}
var f = 10000;
function evaluatePixel(sample) {
return [sample.B3/f*2.5, sample.B2/f*2.5, sample.B1/f*2.5, sample.dataMask];
}
"""
}
)

Pleiades and SPOT data import

Search

Simple Search

To search for Pleiades data, data.constellation must be set to "PHR", and for SPOT data to "SPOT". In both cases provider must be set to "AIRBUS".

url = "https://services.sentinel-hub.com/api/v1/dataimport/search"
query = {
"provider": "AIRBUS",
"bounds": {
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
15.825815,
46.714048
],
[
15.813988,
46.707248
],
[
15.832682,
46.703062
],
[
15.839931,
46.711694
],
[
15.835353,
46.716664
],
[
15.825815,
46.714048
]
]
]
}
},
"data": [
{
"constellation": "PHR",
"dataFilter": {
"timeRange": {
"from":"2017-09-13T10:00:00.00Z",
"to": "2017-09-13T11:00:00.00Z"
}
}
}
]
}
response = oauth.post(url, json=query)
response.raise_for_status()
results = response.json()

To get product ids:

item_ids = [feature["properties"]["id"] for feature in results["features"]]

Please note: Airbus search can return products that don't overlap with the given area of interest. However, orders that include such non-overlapping products are rejected by Airbus. Therefore, Sentinel Hub automatically filters out those products from simple search and when ordering products using a query. Native search, on the other hand, functions purely as a proxy search, thus we don't filter products nor modify responses in other ways.

Native Search

This native search is equivalent to the above simple search. Note the added Airbus-specific field processingLevel.

url = "https://services.sentinel-hub.com/api/v1/dataimport/nativesearch"
payload = {
"provider": "AIRBUS",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
15.825815,
46.714048
],
[
15.813988,
46.707248
],
[
15.832682,
46.703062
],
[
15.839931,
46.711694
],
[
15.835353,
46.716664
],
[
15.825815,
46.714048
]
]
]
},
"constellation": "PHR",
"acquisitionDate": "[2017-09-13T10:00:00.000Z,2017-09-13T11:00:00.000Z]",
"processingLevel" : "ALBUM,SENSOR"
}
response = oauth.post(url, json=payload)
response.raise_for_status()
results = response.json()

To get product ids:

item_ids = [feature["properties"]["id"] for feature in results["features"]]

To get info on how to use the native search, you can check this Airbus guide.

Thumbnail

After searching for data, you can check the thumbnail of each item by entering the item id into the url of the thumbnail request. The example below requests a thumbnail for Pleiades data. To request a thumbnail for SPOT data, replace the string AIRBUS_PLEIADES in the url with AIRBUS_SPOT.

item_id = '6701559b-e11e-43f9-b395-ac04f193a83b'
# or get it from search results: item_id = item_ids[0]
url = f"https://services.sentinel-hub.com/api/v1/dataimport/collections/AIRBUS_PLEIADES/products/{item_id}/thumbnail"
response = oauth.get(url)

The thumbnail can be displayed in Python using:

import io
from PIL import Image
image_bytes = io.BytesIO(response.content)
Image.open(image_bytes)

Order

To order Pleaides data, input.data.constellation must be set to "PHR", and for SPOT data to "SPOT". In both cases provider must be set to "AIRBUS".

Order products

To order the import of the products, which we got as a result of search and are stored in the variable item_ids:

url = "https://services.sentinel-hub.com/api/v1/dataimport/orders"
payload = {
"name": "airbus products",
# collectionId is optional. Remove it to create a new collection.
"collectionId": "<your Pleiades/SPOT collectionId>",
"input": {
"provider": "AIRBUS",
"bounds": {
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
15.825815,
46.714048
],
[
15.813988,
46.707248
],
[
15.832682,
46.703062
],
[
15.839931,
46.711694
],
[
15.835353,
46.716664
],
[
15.825815,
46.714048
]
]
]
}
},
"data": [
{
"constellation": "PHR",
"products": [
{
"id": item_ids[0]
}
]
}
]
}
}
response = oauth.post(url, json=payload)
response.raise_for_status()
results = response.json()

Order using query

Another way to order data is using search query, in this case using query from above:

url = "https://services.sentinel-hub.com/api/v1/dataimport/orders"
payload = {
"name": "airbus query",
# collectionId is optional. Remove it to create a new collection.
"collectionId": "<your Pleiades/SPOT collectionId>",
"input": query
}
response = oauth.post(url, json=payload)
response.raise_for_status()
order = response.json()

To extract the order id from the response:

order_id = order['id']

To extract the cost in square kilometers:

sqkm = order['sqkm']

Confirm the order

Confirming the order will subtract the ordered area in km2 from your quota.

To initiate import, confirm the order:

url = f"https://services.sentinel-hub.com/api/v1/dataimport/orders/{order_id}/confirm"
response = oauth.post(url)
response.raise_for_status()

Get order information

url = f"https://services.sentinel-hub.com/api/v1/dataimport/orders/{order_id}"
response = oauth.get(url)
response.raise_for_status()
order = response.json()

To extract the order status:

status = order['status']

To extract the BYOC collection ID:

collection_id = order['collectionId']

List all your orders

url = "https://services.sentinel-hub.com/api/v1/dataimport/orders"
response = oauth.get(url)
response.raise_for_status()
response.json()

Access Pleiades data in a BYOC collection and process a truecolor image

This is a normal Process API request that uses a BYOC collectionId that can be fetched from the get order information request.

response = oauth.post('https://services.sentinel-hub.com/api/v1/process',
headers={"Authorization" : "Bearer <your_access_token>"},
json={
'input': {
"bounds": {
"properties": {
"crs": "http://www.opengis.net/def/crs/EPSG/0/32633"
},
"bbox": [562218,5174019,564201,5172501]
},
"data": [{
"type": "byoc-<collectionId>",
"dataFilter": {
"timeRange": {
"from": "2017-09-13T00:00:00Z",
"to": "2017-09-13T23:59:59Z"
}
}
}
]
},
"output": {
"width": 512,
"height": 512
},
"evalscript": """
//VERSION=3
function setup() {
return {
input: ["B0", "B1", "B2", "dataMask"],
output: { bands: 4 }
};
}
var f = 2000;
function evaluatePixel(sample) {
return [sample.B2/f, sample.B1/f, sample.B0/f, sample.dataMask];
}
"""
}
)

WorldView data import

Search

Simple Search

url = "https://services.sentinel-hub.com/api/v1/dataimport/search"
query = {
"provider": "MAXAR",
"bounds": {
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
15.81,
46.70
],
[
15.84,
46.70
],
[
15.84,
46.72
],
[
15.81,
46.72
],
[
15.81,
46.70
]
]
]
}
},
"data": [
{
"productBands": "4BB",
"dataFilter": {
"timeRange": {
"from": "2020-11-06T00:00:00.0Z",
"to": "2020-11-06T23:59:59.9Z"
}
}
}
]
}
response = oauth.post(url, json=query)
response.raise_for_status()
results = response.json()

To get product ids:

item_ids = [feature["catalogID"] for feature in results["features"]]

Native Search

This native search is equivalent to the above simple search.

url = "https://services.sentinel-hub.com/api/v1/dataimport/nativesearch"
payload = {
"provider": "MAXAR",
"startDate": "2020-11-06",
"endDate": "2020-11-07",
"aoiInGeoJson": {
"type": "Polygon",
"coordinates": [
[
[
15.81,
46.70
],
[
15.84,
46.70
],
[
15.84,
46.72
],
[
15.81,
46.72
],
[
15.81,
46.70
]
]
],
"crs": {
"type": "name",
"properties": {
"name": "EPSG:4326"
}
}
},
"geometry": "true"
}
response = oauth.post(url, json=payload)
response.raise_for_status()
results = response.json()

To get product ids:

item_ids = [feature["catalogID"] for feature in results["features"]]

Thumbnail

After searching for data, you can check the thumbnail of each item by entering the item id into the url of the thumbnail request:

item_id = '1040010063790D00'
# or get it from search results: item_id = item_ids[0]
url = f"https://services.sentinel-hub.com/api/v1/dataimport/collections/MAXAR_WORLDVIEW/products/{item_id}/thumbnail"
response = oauth.get(url)

The thumbnail can be displayed in Python using:

import io
from PIL import Image
image_bytes = io.BytesIO(response.content)
Image.open(image_bytes)

Order

To order WorldView data, provider must be set to "MAXAR".

Order products

To order the import of the products, which we got as a result of search and are stored in the variable item_ids:

url = "https://services.sentinel-hub.com/api/v1/dataimport/orders"
payload = {
"name": "My WorldView order",
# collectionId is optional. Remove it to create a new collection.
"collectionId": "<your WorldView collectionId>",
"input": {
"provider": "MAXAR",
"bounds": {
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
15.81,
46.70
],
[
15.84,
46.70
],
[
15.84,
46.72
],
[
15.81,
46.72
],
[
15.81,
46.70
]
]
]
}
},
"data": [{
"productBands": "4BB",
"selectedImages": item_ids
}]
}
}
response = oauth.post(url, json=payload)
response.raise_for_status()
order = response.json()

Order using query

Another way to order data is using search query, in this case using the query from above:

url = "https://services.sentinel-hub.com/api/v1/dataimport/orders"
payload = {
"name": "My WorldView order using query",
# collectionId is optional. Remove it to create a new collection.
"collectionId": "<your WorldView collectionId>",
"input": query
}
response = oauth.post(url, json=payload)
response.raise_for_status()
order = response.json()

To extract the order id from the response:

order_id = order['id']

To extract the cost in square kilometres:

sqkm = order['sqkm']

Confirm the order

Confirming the order will subtract the ordered area in km2 from your quota. To initiate import, confirm the order:

url = f"https://services.sentinel-hub.com/api/v1/dataimport/orders/{order_id}/confirm"
response = oauth.post(url)
response.raise_for_status()

Get order information

url = f"https://services.sentinel-hub.com/api/v1/dataimport/orders/{order_id}"
response = oauth.get(url)
response.raise_for_status()
order = response.json()

To extract the order status:

status = order['status']

To extract the BYOC collection ID:

collection_id = order['collectionId']

List all your orders

url = "https://services.sentinel-hub.com/api/v1/dataimport/orders"
response = oauth.get(url)
response.raise_for_status()
response.json()

Access WorldView data in a BYOC collection and process a truecolor image

This is a normal Process API request that uses a BYOC collectionId that can be fetched from the get order information request. More examples are available here.

url = 'https://services.sentinel-hub.com/api/v1/process'
payload = {
'input': {
"bounds": {
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
15.81,
46.70
],
[
15.84,
46.70
],
[
15.84,
46.72
],
[
15.81,
46.72
],
[
15.81,
46.70
]
]
]
}
},
"data": [{
"type": "byoc-991fe3be-4d19-4d9f-9941-879da0a5c3b3",
"dataFilter": {
"timeRange": {
"from": "2020-11-06T00:00:00.0Z",
"to": "2020-11-06T23:59:59.9Z"
}
}
}
]
},
"output": {
"width": 512,
"height": 512
},
"evalscript": """
//VERSION=3
function setup() {
return {
input: ["Red", "Green", "Blue", "dataMask"],
output: { bands: 4 }
};
}
var f = 2000;
function evaluatePixel(sample) {
return [sample.Red/f, sample.Green/f, sample.Blue/f, sample.dataMask];
}
"""
}
response = oauth.post(url, json=payload)
response.raise_for_status()