Tasking Order creation, editing and deletion

last updated: December 10, 2024

The Planet Tasking API is a REST based API, which can be integrated into any service regardless of the language used. Below are some examples of how to integrate the most commonly used aspects of the Tasking API Orders creation, editing and cancellation methods.

Tasking Order creation

The creation of an order via the Tasking API is done by sending a POST request to the Tasking API tasking/v2/orders endpoint. The creation of Tasking Order can be as simple as the following request example:

curl --request POST --url 'https://api.planet.com/tasking/v2/orders/' \
    --header 'accept: application/json' \
    --header 'authorization: api-key <YOUR_API_KEY>' \
    --header 'content-type: application/json' \
    --data '{
        'name': 'Order 01',
        'geometry': {
            'type': 'Point',
            'coordinates': [
                149.44135,
                28.49240
            ]
        }
    }

Defining the minimum and maximum Satellite elevation angles

It is possible, as part of the Tasking Order creation request, to define the desired range of angles relative to the target that the satellite should attempt to take an image. These values are sat_elevation_angle_min and sat_elevation_angle_max, and whilst both have a theoretical range from 0° to 90° it is likely that these values will be defined in your contract as having a range between 60° and 90° inclusive. These angles are relative to the target, so 90° is directly above the target, and it should be noted that the more restrictive the range between the min and max values the more likely it is that you Tasking Order will not succeed.

Selecting the PL-Number and Product

If the PL-Number and Product are not defined in the order POST request, then the Tasking API service will select the default values that are defined for the given api-key. In the majority of cases this will be sufficient and thus the PL-Number and Product do not need to be defined. If a different PL-Number and/or product are to be chosen, then these can simply be defined as part of the order payload:

   {
        "name": "Order 01",
        "geometry": {
            "type'": "Point",
            "coordinates": [
                149.44135,
                28.49240
            ]
        },
        "pl_number": "PL-YourPlNumber",
        "product": "one_time_tasking"
   }

The response will contain the UUID that has been generated to identify the newly created Tasking Order, as well as any geometry created and other values related to the Tasking Order:

    {
        "id": "9d79b9ba-efa3-4e6d-bc08-407b545875a1",
        "geometry": {
            "type": "Polygon",
            "coordinates": [
            [
                [
                    149.415829,
                    28.469843
                ],
                [
                    149.466885,
                    28.469843
                ],
                [
                    149.466896,
                    28.514958
                ],
                [
                    149.415818,
                    28.514958
                ],
                [
                    149.415829,
                    28.469843
                ]
            ]
            ]
        },
        "original_geometry": {
            "type": "Point",
            "coordinates": [
                149.441357,
                28.492403
            ]
        },  
        "order_type": "IMAGE",
        "sat_elevation_angle_min": 60.0,
        "sat_elevation_angle_max": 90.0,
        "start_time": "2020-03-23T12:26:35.820963Z",
        "end_time": "2020-04-22T12:26:35.820963Z",
        "n_stereo_pov": null,
        "is_cancellable": false,
        "cancellable_until": "2021-08-05T10:18:00.000000Z",
        "requested_sqkm": 25.0,
        "created_time": "2020-03-23T12:26:36.137220Z",
        "updated_time": "2020-03-23T12:26:36.137259Z",
        "name": "test_order_426",
        "created_by": "a.user@a.fake.email.address.com",
        "status": "RECEIVED",
        "fulfilled_sqkm": 0.0,
        "capture_status_published_count": 0,
        "capture_assessment_success_count": 0,
        "capture_assessment_invalid_count": 0,
        "scheduling_type": "FLEXIBLE",
        "rrule": null,
        "exclusivity_days": 0,
        "next_planned_acquisition_time": null,
        "last_acquired_time": null,
        "imaging_window": null
    }

Strip vs Point

The previous example showed how to create a Point Tasking Order, which takes the provided geo-coordinates and generates a 5x5 km square around that point, giving an overall area of 25 km2. If you have two points geographically close to each other that need to be imaged, or require a longer (but not wider) area to be imaged, then defining a Strip Tasking Order would be more suitable. The difference is simple in that instead of providing a GEoJSON Point in the Tasking Order payload, instead a LineString is provided. For example:

curl --request POST --url 'https://api.planet.com/tasking/v2/orders/' \
    --header 'accept: application/json' \
    --header 'authorization: api-key <YOUR_API_KEY>' \
    --header 'content-type: application/json' \
    --data '{
        'name': 'Order 01',
        'geometry': {
            'type': 'LineString',
            'coordinates': [
                [
                   10.92041015625,
                   48.91527985344383
                ],
                [
                   10.78857421875,
                   49.0738659012854
                ]
            ]
        }
    }

Strip Tasking Orders have a fixed width of 5 km and a minimum length of 6 km and a maximum length of 100 km.

Retrieving, filtering and paginating your Tasking Orders

Once you have created your Tasking Order, you can check up on it and any other Tasking Orders you may have created by performing a GET request on the same /orders endpoint that you used to create your Tasking Orders:

curl --request GET \
  --url https://api.planet.com/tasking/v2/orders/ \
  --header 'Authorization: api-key <YOUR_API_KEY>' \
  --header 'Content-Type: application/json'

If you want to retrieve a specific Tasking Order, you would simply append the ID of the Tasking Order to the URL, e.g. /orders/some_UUID_number

In the event that you have multiple Tasking Orders, the /orders endpoint provides filtering and pagination to help manage the response payload. Through filtering you can ensure that only those Tasking Orders that you want to see are returned. Tasking Orders can be filtered by created, start and end times, name and many other values (for a full list of available parameters see: https://developers.planet.com/docs/tasking/reference/#operation/v2_orders_list) Below is an example of request all Tasking Orders that have a name containing a given string and that were created after a particular date. Note that the created date must be a correctly formatted date/time value of the type "YYYY-mm-ddThh:mm:ssZ" and that all time are in UTC:

curl --request GET \
  --url 'https://api.planet.com/tasking/v2/orders/?name__icontains=test&created_time__gt=2021-01-01T23:59:59Z' \
  --header 'Authorization: api-key <YOU_API_KEY>' \
  --header 'Content-Type: application/json'

The parameters limit and offset are used to define the boundaries of the response pagination. limit defines how many results are returns per page and offset determines the starting index of the response. Taking this into account, the following request would return 30 results per page, starting with the 10th possible result:

curl --request GET \
  --url 'https://api.planet.com/tasking/v2/orders/?limit=30&offset=10' \
  --header 'Authorization: api-key <YOU_API_KEY>' \
  --header 'Content-Type: application/json'

The response payload will then include the key next and previous with the corresponding values containing URLs that will point to the next and previous page of results. The format of these URLs is the same as the original request in the above example.

Tasking Order Editing

The ability to edit an existing Tasking Order depends upon what needs to be changed as well as the current status of the Tasking Order in the system. The following table shows what can be edited and in what state. Tasking Orders in the following states FULFILLED, CANCELLED, REJECTED and EXPIRED cannot be edited :

FIELD PENDING IN_PROGRESS
start_time yes no
end_time yes yes

Rather than a POST request, an edit requires a PUT request to be made. The following command would edit the name and start time of a an existing Tasking Order. The UUID that identifies the order is including as part of the URL:

 curl --request PUT --url 'https://api.planet.com/tasking/v2/orders/<ORDER_ID_GOES_HERE>' \
    --header 'accept: application/json' \
    --header 'authorization: api-key <YOUR_API_KEY>' \
    --header 'content-type: application/json' \
    --data '{
        'start_time': '2020-04-23T12:26:35Z'
    }

With a response that shows the updated fields plus the other fields that can be edited:

    {
        "start_time": "2020-05-23T12:26:35.000000Z",
        "end_time": "2020-06-23T12:26:35.000000Z"
    }

Tasking Order Deletion

Tasking Order deletion follows similar rules to editing. Tasking Orders can be deleted or cancelled only when the Tasking Order is in one of the following states: PENDING, IN_PROGRESS and RECEIVED. A Tasking Order deletion is acheived by creating a DELETE request to the tasking/v2/orders endpoint with the ID of the Tasking Order that is to be deleted:

curl --request DELETE --url 'https://api.planet.com/tasking/v2/orders/<ORDER_ID_GOES_HERE>' \
    --header 'accept: application/json' \
    --header 'authorization: api-key <YOUR_API_KEY>' \
    --header 'content-type: application/json'

Note the lack of a body in the request. A successful request receives a HTTP 204 response

Tasking Order Pricing

Users can obtain detailed pricing information for an order (created after March 2024) by using the GET /orders/:order_id/pricing endpoint:

curl --request GET \
    --url https://api.planet.com/tasking/v2/orders/<ORDER_ID_GOES_HERE>/pricing \
    --header 'Authorization: api-key <YOUR_API_KEY>' \
    --header 'Content-Type: application/json'

The response provides information on how the price was calculated by specifying quota units, the determined_by field (which can be either pricing_model or replaced_orders), and applied multipliers.

Example of pricing determined by pricing_model

    {
        "order_id": "87c66e26-adf5-4109-85b7-2056347372ea",
        "units": "SQKM",
        "estimated_quota_cost": 70.48,
        "determined_by": "pricing_model",
        "pricing_model": {
            "base_price": 70.48,
            "multipliers": [
                {
                    "name": "imaging_mode",
                    "value": 1.0,
                    "description": "single-image"
                }
            ]
        }
    }

Example of pricing determined by replaced_orders

If determined_by is replaced_orders it means that some other orders had to be cancelled to create this order. In this case, estimated_quota_cost is the sum of the replaced orders:

    {
    "order_id": "b79eaa77-8d74-4803-9dba-dbc33760021f",
    "units": "SQKM",
    "estimated_quota_cost": 75.0,
    "determined_by": "replaced_orders",
    "pricing_model": {
        "base_price": 25.0,
        "multipliers": [
            {
                "name": "imaging_mode",
                "value": 1.0,
                "description": "normal"
            },
            {
                "name": "tasking_tier",
                "value": 1.0,
                "description": "normal"
            }
        ]
    },
    "replaced_orders": [
        {
            "order_id": "b9635a07-ee04-4b7b-9406-222444167018",
            "name": "PLANET_476-fb96f79c-a973-4815-9817-b7dd2e84c32a_240424_250424_11",
            "cost": 25.0
        },
        {
            "order_id": "acd778f0-c490-4c9b-916a-5d736db4b04f",
            "name": "PLANET_475-228e2124-3d6b-477c-a3f8-b25e9a17fb40_240424_250424_11",
            "cost": 25.0
        },
        {
            "order_id": "38a34626-71a3-448b-acd5-76831b4da9c8",
            "name": "PLANET_471-c607489a-8b4d-42af-86c9-54cbd3690028_240424_250424_11",
            "cost": 25.0
        }
    ]
}

Preliminary Tasking Order Pricing (Pricing Preview)

Users can obtain detailed estimated pricing information before creating an order by using the POST /pricing/ endpoint and sending an order-like payload as the input. The required fields for requesting the pricing are:

  • geometry: a GeoJSON object
  • imaging_window: ID of the imaging window (ASSURED orders only)

All other fields are optional (see Tasking Order creation).

Single order estimation

curl --request POST \
    --url https://api.planet.com/tasking/v2/pricing/ \
    --header 'Authorization: api-key <YOUR_API_KEY>' \
    --header 'Content-Type: application/json' \
    --data '{
        "pl_number": "PL-1163400",
        "product": "Assured Tasking",
        "geometry": {"type":"Point","coordinates":[40.716725,64.598217]}
    }'

The response is the same as for an existing order pricing (see Tasking Order Pricing) excluding order_id.

Multiple orders estimation (bulk)

curl --request POST \
  --url https://api.planet.com/tasking/v2/pricing/ \
  --header 'Authorization: api-key <YOUR_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '[{
        "geometry": {"type":"Point","coordinates":[40.716725,64.598217]}
    },
    {
        "geometry": {"type":"Point","coordinates":[40.716725,64.598217]}
    }]'

The response includes pricing_details array containing pricing information for each order payload (in the same order as the orders input payload), and a total_estimated_quota_cost, which is the sum of the estimated_quota_cost for each order:

{
    "total_estimated_quota_cost": 50.0,
    "pricing_details": [
        {
            "units": "SQKM",
            "estimated_quota_cost": 25.0,
            "determined_by": "pricing_model",
            "pricing_model": {
                "base_price": 25.0,
                "multipliers": [
                    {
                        "name": "imaging_mode",
                        "description": "single-image",
                        "value": 1.0
                    }
                ]
            }
        },
        {
            "units": "SQKM",
            "estimated_quota_cost": 25.0,
            "determined_by": "pricing_model",
            "pricing_model": {
                "base_price": 25.0,
                "multipliers": [
                    {
                        "name": "imaging_mode",
                        "description": "single-image",
                        "value": 1.0
                    }
                ]
            }
        }
    ]
}

In the event of partial failures, errors are returned for the corresponding order input payload and are not included in the calculation of total_estimated_quota_cost:

{
    "total_estimated_quota_cost": 88.775,
    "pricing_details": [
        {
            "message": {
                "error": "Failed to calculate order pricing."
            }
        },
        {
            "units": "SQKM",
            "estimated_quota_cost": 25.0,
            "determined_by": "pricing_model",
            "pricing_model": {
                "base_price": 25.0,
                "multipliers": [
                    {
                        "name": "imaging_mode",
                        "description": "single-image",
                        "value": 1.0
                    }
                ]
            }
        },
        {
            "units": "SQKM",
            "estimated_quota_cost": 63.775,
            "determined_by": "pricing_model",
            "pricing_model": {
                "base_price": 63.775,
                "multipliers": [
                    {
                        "name": "imaging_mode",
                        "description": "single-image",
                        "value": 1.0
                    }
                ]
            }
        }
    ]
}


We are continually working to improve our technical documentation and support. Please help by sharing your experience with us.

Send Us Your Feedback