Detect and Classify
Learn how to add Detect and Classify (D&C) to your tasking workflow. D&C applies automated detection models to your SAR imagery and delivers structured results identifying objects of interest within the scene.
What is Detect and Classify?
When you task a satellite image through the ICEYE API, you receive SAR data products (GRD, SLC, etc.). D&C goes a step further: it runs detection models on the acquired imagery and returns GeoJSON files containing the locations and classifications of detected objects.
Available detection models
ICEYE currently offers three derivative product types:
| Derivative product type | Description |
|---|---|
|
Detects and classifies aircraft |
|
Detects and classifies vessels |
|
Detects and classifies ground vehicles (military and civilian, including trucks, tanks, cars, and armored vehicles) |
You can request one or more of these in a single task.
How it works
D&C is not a separate API. It extends the existing tasking workflow with two additions:
-
You include a
derivativeProductTypesparameter when creating a task -
After the task is fulfilled, you retrieve the detection results from a dedicated derivatives endpoint
The rest of the workflow (authentication, task creation, monitoring) stays the same.
Prerequisites
Before using D&C, make sure you have:
-
A contract with D&C enabled — derivative product types must be enabled in your contract. Contact your ICEYE representative.
-
Valid authentication credentials — see Authentication.
-
A supported imaging mode — derivatives are only available for high-resolution spotlight modes:
SPOTLIGHT,SPOTLIGHT_FINE,SPOTLIGHT_FINE_1L,SPOTLIGHT_EXTENDED_DWELL, andSPOTLIGHT_EXTENDED_DWELL_FINE. Other modes (e.g., STRIPMAP, SCAN) are not supported.
Part 1: Creating a task with D&C
Creating a D&C task is identical to creating a regular task, with one addition: the derivativeProductTypes field in the request body.
The derivativeProductTypes parameter
This parameter accepts an array of derivative product type strings. Add it alongside your usual task parameters:
"derivativeProductTypes": ["DC_AIRCRAFT", "DC_VESSELS"]
D&C processing uses the GRD image as input. You must explicitly include GRD in the productTypes parameter of your task request. It is not sufficient for GRD to be a default product in your contract. For the full list of validation rules and error codes, see Create task — Derivative product types.
|
Full request example
-
cURL
-
Python
-
JavaScript
curl --location "${API_BASE_URL}/api/tasking/v2/tasks" \
--header "Content-Type: application/json" \
--header "Accept: application/json, application/problem+json" \
--header "Authorization: Bearer ${API_ACCESS_TOKEN}" \
--data '{
"acquisitionWindow": {
"start": "2026-03-01T00:00:00Z",
"end": "2026-03-02T00:00:00Z"
},
"contractID": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"imagingMode": "SPOTLIGHT",
"pointOfInterest": {
"lat": 60.1699,
"lon": 24.9384
},
"productTypes": ["GRD"],
"derivativeProductTypes": ["DC_AIRCRAFT", "DC_VESSELS"]
}'
import requests
task_payload = {
"acquisitionWindow": {
"start": "2026-03-01T00:00:00Z",
"end": "2026-03-02T00:00:00Z"
},
"contractID": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"imagingMode": "SPOTLIGHT",
"pointOfInterest": {
"lat": 60.1699,
"lon": 24.9384
},
"productTypes": ["GRD"],
"derivativeProductTypes": ["DC_AIRCRAFT", "DC_VESSELS"]
}
response = requests.post(
f"{API_BASE_URL}/api/tasking/v2/tasks",
headers={
"Content-Type": "application/json",
"Accept": "application/json, application/problem+json",
"Authorization": f"Bearer {access_token}"
},
json=task_payload
)
task = response.json()
print(f"Task created: {task['id']}, status: {task['status']}")
const taskPayload = {
acquisitionWindow: {
start: "2026-03-01T00:00:00Z",
end: "2026-03-02T00:00:00Z"
},
contractID: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
imagingMode: "SPOTLIGHT",
pointOfInterest: {
lat: 60.1699,
lon: 24.9384
},
productTypes: ["GRD"],
derivativeProductTypes: ["DC_AIRCRAFT", "DC_VESSELS"]
};
const response = await fetch(`${API_BASE_URL}/api/tasking/v2/tasks`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json, application/problem+json",
"Authorization": `Bearer ${accessToken}`
},
body: JSON.stringify(taskPayload)
});
const task = await response.json();
console.log(`Task created: ${task.id}, status: ${task.status}`);
Response
On success, you receive a 201 status code.
The response confirms which derivative product types were requested:
{
"id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"pointOfInterest": {
"lat": 60.1699,
"lon": 24.9384
},
"acquisitionWindow": {
"start": "2026-03-01T00:00:00Z",
"end": "2026-03-02T00:00:00Z"
},
"createdAt": "2026-02-18T10:00:00Z",
"updatedAt": "2026-02-18T10:00:00Z",
"imagingMode": "SPOTLIGHT",
"contractID": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"status": "RECEIVED",
"exclusivity": "PRIVATE",
"priority": "COMMERCIAL",
"sla": "SLA_8H",
"eula": "STANDARD",
"incidenceAngle": {
"min": 20,
"max": 35
},
"lookSide": "ANY",
"passDirection": "ANY",
"productTypes": ["GRD"],
"derivativeProductTypes": ["DC_AIRCRAFT", "DC_VESSELS"]
}
The derivativeProductTypes array in the response mirrors what you requested.
If a derivative type is not supported by your contract, the API returns an error.
Part 2: Monitoring the task
D&C processing starts automatically after the task is fulfilled and the SAR products are available. There is nothing different about monitoring a D&C task. Use the same polling approach as any other task.
Polling for status
-
cURL
-
Python
-
JavaScript
curl --location "${API_BASE_URL}/api/tasking/v2/tasks/${taskID}" \
--header "Accept: application/json, application/problem+json" \
--header "Authorization: Bearer ${API_ACCESS_TOKEN}"
import time
while True:
response = requests.get(
f"{API_BASE_URL}/api/tasking/v2/tasks/{task_id}",
headers={"Authorization": f"Bearer {access_token}"}
)
task = response.json()
print(f"Status: {task['status']}")
if task["status"] in ["FULFILLED", "DONE", "FAILED", "REJECTED", "CANCELED"]:
break
time.sleep(30)
async function waitForFulfillment(taskId) {
const terminalStates = ["FULFILLED", "DONE", "FAILED", "REJECTED", "CANCELED"];
while (true) {
const response = await fetch(
`${API_BASE_URL}/api/tasking/v2/tasks/${taskId}`,
{ headers: { "Authorization": `Bearer ${accessToken}` } }
);
const task = await response.json();
console.log(`Status: ${task.status}`);
if (terminalStates.includes(task.status)) return task;
await new Promise(resolve => setTimeout(resolve, 30000));
}
}
Wait for the task status to reach FULFILLED or DONE.
Once the SAR products are ready, D&C processing begins in the background.
At that point, move on to Part 3 and start polling the derivatives endpoint for results.
Part 3: Retrieving D&C results
Once the task status is FULFILLED or DONE, start polling the derivatives endpoint.
D&C processing runs asynchronously after the SAR products are available, so the derivatives may not be ready immediately.
Request
-
cURL
-
Python
-
JavaScript
curl --location "${API_BASE_URL}/api/tasking/v2/tasks/${taskID}/derivatives" \
--header "Accept: application/json, application/problem+json" \
--header "Authorization: Bearer ${API_ACCESS_TOKEN}"
response = requests.get(
f"{API_BASE_URL}/api/tasking/v2/tasks/{task_id}/derivatives",
headers={"Authorization": f"Bearer {access_token}"}
)
if response.status_code == 200:
print("All derivatives ready")
elif response.status_code == 206:
print("Some derivatives still processing")
elif response.status_code == 404:
print("No derivatives available yet, keep polling")
derivatives = response.json()
for derivative in derivatives["data"]:
print(f"Type: {derivative['derivativeProductType']}")
for asset in derivative.get("assets", []):
print(f" Download: {asset['href']}")
const response = await fetch(
`${API_BASE_URL}/api/tasking/v2/tasks/${taskId}/derivatives`,
{ headers: { "Authorization": `Bearer ${accessToken}` } }
);
if (response.status === 200) {
console.log("All derivatives ready");
} else if (response.status === 206) {
console.log("Some derivatives still processing");
} else if (response.status === 404) {
console.log("No derivatives available yet, keep polling");
}
const derivatives = await response.json();
for (const derivative of derivatives.data) {
console.log(`Type: ${derivative.derivativeProductType}`);
for (const asset of derivative.assets || []) {
console.log(` Download: ${asset.href}`);
}
}
Understanding the response status codes
The endpoint returns one of three status codes:
200(All derivatives ready)-
All requested derivative products have been processed and are available for download. You can stop polling.
206(Partial content)-
Some derivative products are available, but others are still being processed. Continue polling until you receive a
200. 404(Not found)-
No derivative products are available yet. The GRD product may still be processing, or derivative processing has not started. Keep polling.
Poll the endpoint periodically (for example, every 30 seconds) until you receive a 200 response.
For the full list of error responses, see Task derivatives.
Response body
The response contains a data array with one entry per derivative product:
{
"data": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"derivativeProductType": "DC_AIRCRAFT",
"imageReference": "c2ac555e-27ac-4c6a-bf87-717fa81539e3",
"assets": [
{
"type": "geojson",
"href": "https://XXXXXXXXXXXX.cloudfront.net/XXXX/aircraft-detections.geojson?Expires=..."
}
]
},
{
"id": "7ba92e11-3344-4a8b-9c12-abcdef123456",
"derivativeProductType": "DC_VESSELS",
"imageReference": "c2ac555e-27ac-4c6a-bf87-717fa81539e3",
"assets": [
{
"type": "geojson",
"href": "https://XXXXXXXXXXXX.cloudfront.net/XXXX/vessel-detections.geojson?Expires=..."
}
]
}
]
}
Each derivative entry contains:
-
id— unique identifier for the derivative record -
derivativeProductType— which detection model produced this result (e.g.,DC_AIRCRAFT) -
imageReference— UUID reference to the source image used for processing -
imageId— alternative string identifier for the source image (optional, may be omitted) -
assets— array of downloadable files with signed URLs
| Download URLs are signed and expire after 1 hour. Do not store the URLs for long-term access. Request fresh URLs by calling the derivatives endpoint again. |
Part 4: Downloading D&C results
The assets array contains signed URLs pointing to GeoJSON files.
Download them like any other file:
-
cURL
-
Python
-
JavaScript
curl --location "${DERIVATIVE_ASSET_URL}" \
--output aircraft-detections.geojson
for derivative in derivatives["data"]:
for asset in derivative.get("assets", []):
download_response = requests.get(asset["href"])
filename = f"{derivative['derivativeProductType'].lower()}.geojson"
with open(filename, "wb") as f:
f.write(download_response.content)
print(f"Downloaded {filename}")
for (const derivative of derivatives.data) {
for (const asset of derivative.assets || []) {
const downloadResponse = await fetch(asset.href);
const content = await downloadResponse.text();
const filename = `${derivative.derivativeProductType.toLowerCase()}.geojson`;
// Save or process the GeoJSON content
console.log(`Downloaded ${filename}: ${content.length} bytes`);
}
}
Part 5: Understanding the GeoJSON results
Each D&C result is a standard GeoJSON FeatureCollection with two top-level fields:
{
"type": "FeatureCollection",
"properties": { ... },
"features": [ ... ]
}
-
properties— metadata about the detection model (model type, version, and description) -
features— array of individual detections
Detection features
Each feature in the features array represents a single detected object.
The geometry is a Polygon describing the oriented bounding box of the detected object.
The properties contain the classification details.
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[144.908385, -37.844419],
[144.910070, -37.846546],
[144.909335, -37.846911],
[144.907651, -37.844785],
[144.908385, -37.844419]
]
]
},
"properties": {
"title": "Container Ship",
"supercategory": "Ship",
"category": "Civil",
"subcategory": "Cargo",
"type": "Container Ship",
"class_id": "containership",
"length": 260.0,
"score": 0.998,
"det_score": 0.772,
"alt_title": "Unknown/other type",
"alt_class_id": "unknown",
"alt_score": 0.0001
}
}
Common feature properties
All detection models return the following properties for each detected object:
| Property | Description |
|---|---|
|
Human-readable name of the detected object (e.g., "Container Ship", "Attack/Fighter/Fighter-bomber", "Transport") |
|
Top-level grouping (e.g., "Ship", "Aircraft", "Vehicle") |
|
Broad classification (e.g., "Civil", "Military", "Airplane", "Transport") |
|
More specific grouping (e.g., "Cargo", "Attack/Fighter/Fighter-bomber", "Missile Launcher") |
|
Machine-readable identifier for the classification (e.g., |
|
Classification confidence score (0 to 1). Higher values indicate greater confidence in the classification |
|
Alternative classification if the model considered a second possibility |
|
Alternative top-level grouping |
|
Alternative broad classification |
|
Alternative specific grouping |
|
Machine-readable identifier for the alternative classification |
|
Confidence score for the alternative classification |
Model-specific properties
Each detection model may include additional properties specific to the type of object being detected:
Vessels (DC_VESSELS):
-
type/alt_type— detailed vessel type (e.g., "Container Ship", "Motor Hopper") -
length— estimated length of the vessel in meters -
det_score— detection confidence score (0 to 1), indicating how confident the model is that an object exists at this location
Aircraft (DC_AIRCRAFT):
-
fighter_class/alt_fighter_class— detailed fighter subclass, available for the "Attack/Fighter/Fighter-bomber" category (recommended for Dwell modes) -
fighter_score/alt_fighter_score— confidence scores for the fighter subclass classification
Vehicles (DC_VEHICLES):
-
det_score— detection confidence score (0 to 1), indicating how confident the model is that an object exists at this location
Additional metadata fields may be present depending on the derivative product type.
Geometry
The detection geometry is always a Polygon with five coordinate pairs (a closed rectangle).
This represents an oriented bounding box around the detected object, aligned with the object’s orientation rather than with the cardinal directions.
The coordinates use the WGS 84 (EPSG:4326) coordinate reference system, with longitude first and latitude second, following the GeoJSON specification.
Complete workflow summary
Here is the end-to-end D&C workflow:
1. Create task (with derivativeProductTypes and GRD in productTypes)
|
v
2. Poll task status (GET /tasks/{id}) until FULFILLED or DONE
|
v
3. Download SAR products (GET /tasks/{id}/products)
|
v
4. Poll derivatives (GET /tasks/{id}/derivatives)
|
|-- 404: not available yet, keep polling
|-- 206: partial results, keep polling
|
'-- 200: all results ready, stop polling
|
v
Download GeoJSON files from asset URLs
| API call | Frequency | Trigger | Stop condition |
|---|---|---|---|
POST Create Task |
Once |
User requests D&C |
After task created |
GET Task Status |
Periodic |
After task created |
Status is FULFILLED or DONE |
GET Task Products |
Once |
Status is FULFILLED or DONE |
After download |
GET Task Derivatives |
Periodic (until 200) |
After task is FULFILLED or DONE |
Response status is 200 |
If the derivatives endpoint returns 206, wait and retry. D&C processing typically completes shortly after the SAR products are available, but processing time can vary depending on image size and the number of requested derivative types.
|