REST: Map Processing API

Have more questions? Submit a request
This page describes how to use the DroneDeploy map processing engine as a service to generate maps from photos via our API. 
You can produce high-quality 3D maps from your source image sets without building your own photogrammetry pipeline. We'll take you through setting up a plan and image transfer object, adding images, running exports, and accessing the generated tiles.

First, you will need an API Key. More information is also available on our Data API.

 

In this article: 

  1. Creating Plans 
  2. Creating an Image Transfer
  3. Including GCPs in your Transfer
  4. Including PPK in your Transfer
  5. Multispectral Image Transfers
  6. Example Workflow with Python

 

Create a "Plan"

The Plan object is the central element to much of the DroneDeploy process. It is the container for all of the critical information about your map, and is required for many of the other operations you'll be performing with the API. Fortunately, setting up a plan with default values is easy.

POST /v2/plans

Post Body

{
  "name":"My Plan",
  "workflow": {
    "job_type": "3d"
  },
  "folder_id": "6711a18aaa92c1a8467d251b",
  "record_type": "map_plan"
}

Curl Request

curl -H "Content-Type: application/json" -X POST -d '{ "name":"My Plan", "workflow": { "job_type": "3d" }, "folder_id": "{folder_id}", "record_type": "map_plan"}' "https://public-api.dronedeploy.com/v2/plans?api_key={api_key}"

Example Response

{"id": "58b0490c95b03d000114a881"}
  • folder_id: The id of the Project you would like to associate this Plan to. This is an optional field that allows you to create a Project for viewing within DroneDeploy.com. If you choose to not associate a Project ID, you will still be able to process map data and export, but you will be unable to see it on DroneDeploy.com. You can create a Project and get a folder_id via our GraphQL API.
  • name: The name of your plan. It is best to name your plan something unique, although it is not required. Each plan is assigned a unique identifier within the DroneDeploy system. Defaults to API Generated Plan.
  • job_type: Determines whether the map runs in Terrain ("2d") or Structures ("3d") mode, or if you're using an alternative processing mode such as 360 pano (360_pano, or walkthrough). Defaults to "2d".
  • record_type: The type of the plan being created (map, pano, video, etc.). Available values are map_plan,walkthrough_plan and progress_pano_360_plan. Defaults to map_plan.
  • geometry: The area of the plan in the form of an array of latitude/longitude coordinates (see code example below). If a geometry is not specified (recommended), it will be automatically set to an area around the images upon successful completion of an image transfer. Defaults to null. To create a valid geometry, here are some tips:
    1. The lines of the polygon created by the geometry do not intersect itself. If you were to plot the coordinates in order (clockwise or counter-clockwise) with a line, the line should not cross itself.
    2. The polygon doesn't need to enclose itself (i.e., the last coordinate in the geometry is the same as the first coordinate in the geometry), but will still be valid if it does.
    3. Do not repeat coordinates.

Example geometry:

"geometry": [
  { "lat": 37.7721, "lng": -122.4082 },
  { "lat": 37.7721, "lng": -122.4070 },
  { "lat": 37.7713, "lng": -122.4070 },
  { "lat": 37.7713, "lng": -122.4082 }
]

A Note About Processing Area

You should only specify a geometry if you wish to process the imagery in a specific area. If a geometry is not specified (recommended), it will be automatically set to an area around the images upon successful completion of an image transfer. The map can be cropped down after processing using the crop tool in the web app.

Once a plan has been created, it is time to add some source imagery to the plan.

 

Create an Image Transfer

The Image Transfer object is the way API clients can indicate which source imagery should be used for a given plan. Once an image transfer object is created, the indicated URL is fetched, and the photogrammetry process begins.

While an API client can specify a list of individual images for processing, it is a best practice to create a ZIP archive of all necessary imagery beforehand and specify the compressed file as the URL. This can help ensure completeness of the operation and should reducethe  overall time taken to fetch the source imagery.

We support a few various options for file types. For map processing, input type map_source_image, we support jpeg, png, and tiffs for unprocessed and tiffs for preprocessed maps. For walkthroughs, input typewalkthrough_source_video, we support .insvand .mp4files.  We also support zip archives of these files. If a zip archive is supplied, the archive will be opened and the imagery files downloaded for map processing. Input types image, video, and pano refer to unprocessed assets and will not be included in photogrammetry processing, but instead stored as stored_assets on the associated plan.

We support zip files larger than 2 GB. We recommend using the basic zip archiver built into computers such as Windows. 

 

POST /v2/image_transfer

Post Body

{
"plan_id": "58b0490c95b03d000114a881",
"transport": {"type": "https"},
"inputs": [
{
"location": "https://www.dropbox.com/s/nc2okgk83k439pj/dropbox_example.zip?dl=1",
"type": "map_source_image"
}
]
}

Curl Request

curl -H "Content-Type: application/json" -X POST -d '{"plan_id":"58b0490c95b03d000114a881", "transport": {"type": "https"}, "inputs": [{"location": "https://www.dropbox.com/s/nc2okgk83k439pj/dropbox_example.zip?dl=1", "type": "map_source_image"}]}' "https://public-api.dronedeploy.com/v2/image_transfer?api_key={api_key}"

Example Request

{
  "status": "New", 
  "transport": {"type": "https"},
  "inputs": [
    {"location": "https://www.dropbox.com/s/nc2okgk83k439pj/dropbox_example.zip?dl=1", "type": "map_source_image"}
  ], 
  "plan_id": "58b0490c95b03d000114a881", 
  "failure_info": {}, 
  "id": "58b056b795b03d000114a882", 
  "run_info": {}, 
  "date_complete": null, 
  "date_started": null, 
  "type": "unprocessed", 
  "date_creation": 1487951543526
}

 

Including GCPs

If your plan includes GCPs, you can include the CSV in the request by adding it using the gcp_csv type. The CSV should not be in a .zip and should be linked directly. You should also include the epsgcode for the project.

Post Body

{
	"location": "https://www.dropbox.com/s/nc2okgk83k439pj/gcp_northing_easting_ft.csv", 
	"type": "gcp_csv", 
	"epsg": 6420
}

Curl Request


curl -H "Content-Type: application/json" -X POST -d '{"plan_id":"{plan_id}", "transport": {"type": "https"}, "inputs": [{"location": "https://www.dropbox.com/s/nc2okgk83k439pj/dropbox_example.zip?dl=1", "type": "map_source_image"}, {"location": "https://www.dropbox.com/s/nc2okgk83k439pj/gcp_northing_easting_ft.csv?dl=1", "type": "gcp_csv", "epsg": 6420}]}' "https://public-api.dronedeploy.com/v2/image_transfer?api_key={api_key}"

Example Response with GCPs

{
    "id": "{image_transfer_id}",
    "plan_id": "{plan_id}",
    "type": "unprocessed",
    "status": "new",
    "inputs": [
        {
            "location": "https://www.dropbox.com/s/nc2okgk83k439pj/dropbox_example.zip?dl=1",
            "type": "map_source_image"
        },
        {
            "location": "https://www.dropbox.com/s/nc2okgk83k439pj/gcp_northing_easting_ft.csv?dl=1",
            "type": "gcp_csv"
        }
    ],
    "transport": {
        "type": "https"
    },
    "date_creation": 1701794844591,
    "date_started": null,
    "date_complete": null
}
  

 


Including PPK

If your plan was flown with PPK, you can include the relevant PPK files (.mrk and .obs for DJI, Skydio, or .sbf for Wingtra) in the request in two different ways:

  1. ( Recommended) Include the PPK files in the same .zip files as the images. They will be automatically extracted.

  2. Link the PPK files directly as inputs, using the ppk_data type, as seen below.

Post Body

"inputs": [
  {
	"location": "https://www.dropbox.com/s/nc2okgk83k439pj/DJI_202303151337_005.MRK", 
	"type": "ppk_data"
  },
  {
	"location": "https://www.dropbox.com/s/nc2okgk83k439pj/DJI_202303151337_005.obs", 
	"type": "ppk_data"
  }
]

Multispectral Images

To upload multispectral images, the process is similar to a normal map, with some small changes:

  1. The images or .zip file containing the multispectral images should be type multispectral_source_image instead of map_source_image.

  2. Multispectral imagery is not compatible with GCPs, PPK, or regular map_source_images.

Post Body

"inputs": [
  {
    "location": "https://www.dropbox.com/s/nc2okgk83k439pj/multispectral_images.zip?dl=1",
    "type": "multispectral_source_image"
  }
]

 

 

Monitor progress

Once the Image Transfer object is received, the DroneDeploy Map Engine will fetch the indicated files based on the account type priority settings. Once the files have been fetched, decompressed (if necessary), and validated, map processing will begin.

You can monitor this process by observing the response from the Image_Transfer, then the Plan object. The status will show "Complete" when the download and photogrammetry processes have concluded, respectively.

 

/v2/image_transfer/{id}

To check the status of your image transfer, request the image_transfer API with the ID you were returned when you posted to the endpoint.

Curl Request

curl "https://public-api.dronedeploy.com/v2/image_transfer/58be0da47915d90001962385?api_key={api_key}"

Example Response

{"status": "new", "transport": {"type": "https"}, "inputs": [{"location": "https://dl.dropboxusercontent.com/1/view/asdaafasdasd/ImageTransfer/roofofDD23.zip", "type": "map_source_image"}], "plan_id": "58be0d647915d9000196237b", "date_creation": 1488850340459, "date_complete": null, "date_started": null, "type": "unprocessed", "id": "58be0da47915d90001962385"}

 

/v2/plans/{id}?embed=stored_asset.[download_path,asset_type]

To check the status of your map processing, request the Plan API with the PlanID. The ?embed=stored_asset.[download_path,asset_type] ensures that any stored, unprocessed, assets associated with the plan will be returned in the response body.

Curl Request

curl "https://public-api.dronedeploy.com/v2/plans/58b0490c95b03d000114a881?api_key={api_key}&embed=stored_asset.[download_path,asset_type]"

Example Response

{
    "date_creation": 1487948044752,
    "geometry": [],
    "id": "58b0490c95b03d000114a881",
    "image_count": 1,
    "latest_image_transfer_id": "58b056b795b03d000114a882",
    "latest_started_map": {
        "user_status": "Processing"
    },
    "location": {},
    "log": "1487948044_APIGENERATED",
    "name": "My Plan",
    "stored_assets": []
}

 

 

Example Workflow with Python

import requests
import json

DD_API_KEY = ''
# The ID of the project the Plan should be in. 24 character ObjectID.
FOLDER_ID = ''
# The name of the map_plan that will be created. Can be changed later.
PLAN_NAME = ''
# Files must be made publicly accessible. Signed URLs are commonly used.
# Try navigating to the path in Incognito mode to make sure the file is accessible.
FILE_PATH = ''

# Define the first API endpoint and payload
url_create_plan = f"https://public-api.dronedeploy.com/v2/plans?api_key={DD_API_KEY}"
payload_create_plan = {
    "name": PLAN_NAME,
    "workflow": {"job_type": "3d"},
    "folder_id": FOLDER_ID,
    "record_type": "map_plan", # This is important to specify. 
    # `geometry` is not necessary. If unset, it will be set to an area around the images.
}

# Make the first POST request to create the plan
response_create_plan = requests.post(
    url_create_plan,
    headers={"Content-Type": "application/json"},
    data=json.dumps(payload_create_plan)
)
response_create_plan.raise_for_status() # Raise an exception for bad status codes
plan_data = response_create_plan.json()
plan_id = plan_data.get('id')
print("Plan created successfully!")
print(f"Plan ID: {plan_id}")

# Define the second API endpoint and payload (using the obtained plan_id)
url_image_transfer = f"https://public-api.dronedeploy.com/v2/image_transfer?api_key={DD_API_KEY}"
payload_image_transfer = {
    "plan_id": plan_id,
    "transport": {"type": "https"},
    # map_source_image is the most common input type. It accepts a ZIP, which can contain PPK files.
    # More options are availble for other Plan types.
    "inputs": [
        {"location": FILE_PATH, "type": "map_source_image"}
    ]
}

# Make the second POST request for image transfer
response_image_transfer = requests.post(
    url_image_transfer,
    headers={"Content-Type": "application/json"},
    data=json.dumps(payload_image_transfer)
)
response_image_transfer.raise_for_status() # Raise an exception for bad status codes
print("Image transfer request submitted successfully!")
print(response_image_transfer.json())

 

 

Articles in this section

Was this article helpful?
0 out of 0 found this helpful