# Introduction

Since 2015, tens of thousands of DroneDeploy users have mapped more than 310 million acres in various different industries.

Once a user installs an app it will run on DroneDeploy.com, Android and iOS DroneDeploy apps. All apps are written in HTML, CSS, and JavaScript.


# Overview

DroneDeploy allows external developers to build powerful integrations and extensions of the DroneDeploy platform using:

* &#x20;API - you can use our public APIs to create, read and update data in the DroneDeploy platform


# Introduction

At DroneDeploy we use GraphQL for our main API technology, you can get started with the [API explorer here](https://www.dronedeploy.com/graphiql/).

## What is GraphQL?

GraphQL Is a query language for clients to fetch the data they need from the API. Fundamentally it is:

* A [**specification**](https://spec.graphql.org/October2021/); the specification defines what data can be fetched or updated and defines the format of the response
* Strongly typed; GraphQL has a well defined type system which defines what each field in the API can be and guarantees that it will be that.
* Well structured; the schema not only defines the types of objects and their fields but also defines the links between complex objects. Queries can fetch single objects or traverse the links in the structure to fetch all of the required information in a single query.

### Why use GraphQL?

We are using GraphQL primarily because it allows developers to make API calls which gets them exactly what data they need in the simplest way possible. Since it is a well structured schema you can fetch data and know that you will get the data back in a guaranteed format and because of that, tooling can make development significantly easier.

### Making GraphQL Queries

You can use our API explorer to graphically make API calls: <https://www.dronedeploy.com/graphiql/>

The requests are made making a POST to the \`/graphql\` endpoint, you can make these with CURL or any HTTP compatible client.

One of the top level objects in the query schema is the `viewer` object. This is the User object of the currently logged in user. To query for the currently logged in users username you use the following example:

You can explore this query[ here.](https://www.dronedeploy.com/graphql?query=%7B%20viewer%7B%20username%20%20%0A%7D%20%7D)

```
{
  viewer{
    username    
  }
}
```

Returns:

```javascript
{
  "data": {
    "viewer": {
      "username": "docs@dronedeploy.com"
    }
  }
}
```

The API Explorer is making this request:

```
Content-Type: 
POST /graphql
{
    "query": "{ viewer { username }}"
}
```

You could also make the call using `curl`

```
curl -H 'Content-Type: application/json' \
     -H 'Authorization: Bearer <api key>' \
     -d '{"query": "{ viewer { username }}"}' \
     https://www.dronedeploy.com/graphql
```

## Useful Links:

* The official query documentation is here: <http://graphql.org/learn/queries/>&#x20;
* The official tutorials for learning the basics of GraphQL is here: <http://graphql.org/learn/>


# Authentication

All API requests require an API key to be sent in the Authorization header.

{% hint style="info" %}
**If you already have access to our developer API, contact the** [**DroneDeploy Support Team**](mailto:support@dronedeploy.com) **for help retrieving your API key.**
{% endhint %}

{% hint style="info" %}
**If you would like access to our developer API, contact the** [**DroneDeploy Sales Team**](mailto:sales@dronedeploy.com) **for access to the API key for your enterprise or Developer Partner account.**
{% endhint %}

Once you have your API key it needs to be sent as an `Authorization` header:

```
POST /graphql?   Authorization: Bearer <api_key>
```

Your API key is associated with your own account and so the `viewer` query will return your user account details.

When using the API explorer you simply need to be logged in.


# Pagination

When a one-to-many relationship exists between two nodes, for example organization -> plans, we paginate the responses from the query. Forward, cursor based pagination is used, for more details [see here.](http://graphql.org/learn/pagination/)

## Forward Pagination

The arguments for forward pagination are:

* `first`  a non-negative integer representing the number of results
* `after`: the cursor of which the results will be after

The connection which is returned includes the following fields:

* `pageInfo`: which contains the fields `hasNextPage` and `endCursor` &#x20;
* `edges`: which includes a list of edges. Each edge contains the cursor for that node and the node itself

## Example:

For this example we will go through the organization link to plans.

Firstly we'll get the plans connection with the first two edges:

```
{
  viewer{
    username
    organization {
      plans(first: 2) {
        pageInfo{
          hasNextPage
          endCursor
        }
        edges {
          cursor
          node {
            name            
          }
        }
      }

    }
  }
}
```

This returns:

```
{
  "data": {
    "viewer": {
      "username": "example@dronedeploy.com",
      "organization": {
        "plans": {
          "pageInfo": {
            "hasNextPage": true,
            "endCursor": "YXJyYXljb25uZWN0aW9uOjE="
          },
          "edges": [
            {
              "cursor": "YXJyYXljb25uZWN0aW9uOjA=",
              "node": {
                "name": "Field Map"
              }
            },
            {
              "cursor": "YXJyYXljb25uZWN0aW9uOjE=",
              "node": {
                "name": "Downtown Map"
              }
            }
          ]
        }
      }
    }
  }
}
```

You can see that `hasNextPage` is `true` so we know there are more items and the `endCursor` is set to the last item in the response. Two fetch the next page you simply update the query to include the `after` parameter for the connection:

```
{
  viewer{
    username
    organization {
      plans(first: 2, after:"YXJyYXljb25uZWN0aW9uOjE=") {
        pageInfo{
          hasNextPage
          endCursor
        }
        edges {
          cursor
          node {
            name            
          }
        }
      }

    }
  }
}
```

This returns the data:

```
{
  "data": {
    "viewer": {
      "username": "example@dronedeploy.com",
      "organization": {
        "plans": {
          "pageInfo": {
            "hasNextPage": true,
            "endCursor": "YXJyYXljb25uZWN0aW9uOjM="
          },
          "edges": [
            {
              "cursor": "YXJyYXljb25uZWN0aW9uOjI=",
              "node": {
                "name": "New map"
              }
            },
            {
              "cursor": "YXJyYXljb25uZWN0aW9uOjM=",
              "node": {
                "name": "Untitled Plan"
              }
            }
          ]
        }
      }
    }
  }
}
```


# Examples

In this section you'll be able to see how to construct queries and get the data that you need. You can do this with either the API explorer at [https://www.dronedeploy.com/graphiql/](https://api.dronedeploy.com/graphiql/) or with any HTTP compatible client. See [Introduction](/api/introduction) for details.


# Fetching a Single Object

If you look at the reference documentation you can see on the top level there is a `node` query. This query can fetch any object which implements the `Node` interface, which is almost every object in our API. The `Node` interface defines just one field, the `id` field, so you have to use an [Inline Fragment](https://graphql.org/learn/queries/#fragments) what to do for specific types. Below is some simple examples of how this works.

In this example we'll use the Example Map Plan everyone sees when they first log into DroneDeploy. This has the ID of `MapPlan:5a3d7badf014ce3db3c22391` . You can see the IDs of your own plans by listing your organizations plans, [shown here.](/api/examples/fetching-all-plans-for-your-organization)

The simplest example of using the `node` query is [this.](https://www.dronedeploy.com/graphql?query=query%20getMap%7B%0A%20%20node\(id%3A%22MapPlan%3A5a3d7badf014ce3db3c22391%22\)%7B%0A%20%20%09id%0A%20%20%7D%0A%7D\&operationName=getMap)

```
query getMap{
  node(id:"MapPlan:5a3d7badf014ce3db3c22391"){
    id
  }
}
```

Since the `node` query returns a `Node` object, the only field available is `id`. This isn't very useful, what you want is the fields specific to the `MapPlan` type. For this you use an [Inline Fragment](http://facebook.github.io/graphql/October2016/#sec-Inline-Fragments): You can try this out[ here.](https://www.dronedeploy.com/graphql?query=query%20getMap%7B%0A%20%20node\(id%3A%22MapPlan%3A5a3d7badf014ce3db3c22391%22\)%7B%0A%20%20%09...%20on%20MapPlan%7B%0A%20%20%20%20%20%20name%0A%20%20%20%20%20%20location%20%7B%0A%20%20%20%20%20%20%20%20lat%0A%20%20%20%20%20%20%20%20lng%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20imageCount%0A%20%20%20%20%20%20status%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D\&operationName=getMap)

```
query getMap{
  node(id:"MapPlan:5a3d7badf014ce3db3c22391"){
    ... on MapPlan{
      name
      location {
        lat
        lng
      }
      imageCount
      status
    }
  }
}
```

Which returns the data:

```
{
  "data": {
    "node": {
      "name": "Construction Example",
      "location": {
        "lat": 28.64861527777778,
        "lng": -81.5398111111111
      },
      "imageCount": 438,
      "status": "COMPLETE"
    }
  }
}
```

When you specify the type it allows you to query the fields for that specific type.


# Fetching all Plans for your Organization

## Fetching all Plans for your Organization

Below is the query to fetch all the plans, with their name, geometry, location and the date they were created. Since this is a paged API you also need to fetch the `pageInfo`, [see Pagination](/api/pagination) for more details.

```
query GetPlans{
  viewer{
    organization{
      plans(first:50){
        pageInfo{
          hasNextPage
          endCursor
        }
        edges{
          cursor
          node{
            name
            geometry{
              lat
              lng
            }
            location {
              lat
              lng
            }
            dateCreation
          }
        }
      }
    }
  }
}
```

You can try this query out yourself using [the API explorer here.](https://www.dronedeploy.com/graphql?query=query%20GetPlans%7B%20viewer%7B%20organization%7B%20plans\(first%3A50\)%7B%20pageInfo%7B%20hasNextPage%20endCursor%20%7D%20edges%7B%20cursor%20node%7B%20name%20geometry%7B%20lat%20lng%20%7D%20location%20%7B%20lat%20lng%20%7D%20dateCreation%20%7D%20%7D%20%7D%20%7D%20%7D%20%7D\&operationName=GetPlans)

The top level query `viewer` is the context for the currently logged in user. From this you fetch the `organization` object and the first 50 of the plans associated with that. If you have less than 50 plans you are done. If you have more example you will get a response like this.

```javascript
{
  "data": {
    "viewer": {
      "organization": {
        "plans": {
          "pageInfo": {
            "hasNextPage": true,
            "endCursor": "YXJyYXljb25uZWN0aW9uOjI="
          },
          "edges": [
            ...  // Data removed for the sake of brevity
          ]
        }
      }
    }
  }
}
```

As you can see in the `pageInfo` section `hasNextPage` is True so you know you need to fetch the next page of data. To do this simply modify your query to set the `after` paging parameter to the `endCursor` from the `pageInfo`:

```
query GetPlans{
  viewer{
    organization{
      plans(first:50, after:"YXJyYXljb25uZWN0aW9uOjI="){
        pageInfo{
          hasNextPage
          endCursor
        }
        edges{
          cursor
          node{
            name
            geometry{
              lat
              lng
            }
            location {
              lat
              lng
            }
            dateCreation
          }
        }
      }
    }
  }
}
```

## More Detail

If you look through the schema the `plans` query returns type `Plan`. This is an interface for the common fields across all types of plans. There are more specific types of Plans, specifically `MapPlan` which includes more data such as exports. To fetch these extra fields you need to use an [Inline Fragment](https://graphql.org/learn/queries/#fragments).

[This query:](https://www.dronedeploy.com/graphql?query=query%20GetPlans%7B%20viewer%7B%20organization%7B%20plans\(first%3A50\)%7B%20edges%7B%20node%7B%20name%20...%20on%20MapPlan%7B%20status%20%20%0A%7D%20%7D%20%7D%20pageInfo%7B%20hasNextPage%20endCursor%20%7D%20%7D%20%7D%20%7D%20%7D\&operationName=GetPlans)

```
query GetPlans{
  viewer{
    organization{
      plans(first:50){
        edges{
          node{
            id
            name
            ... on MapPlan{
              status              
            }
          }
        }
        pageInfo{
          hasNextPage
          endCursor
        }
      }
    }
  }
}
```

This specifies that you are looking for the `id` and `name` of all plans, but for objects of type `MapPlan` you want the `status` of the processing as well.


# Fetching Exports

To fetch the exports you first need to fetch the `MapPlan`. You can do this by using the `node` query. For details see the [Fetching a Single Object](/api/examples/fetching-a-single-object) section.

[Click here to view this example in the API explorer, substitute your own plan\_id to execute the query.](https://www.dronedeploy.com/graphql?operationName=null\&query=query%7B%0A%20%20node\(id%3A%22MapPlan%3A5a0de0835f1e08eaabc732bd%22\)%7B%0A%20%20%20%20...%20on%20MapPlan%7B%0A%20%20%20%20%20%20exports\(first%3A5\)%7B%0A%20%20%20%20%20%20%20%20edges%20%7B%0A%20%20%20%20%20%20%20%20%20%20node%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20id%0A%20%20%20%20%20%20%20%20%20%20%20%20user%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20username%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20parameters%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20projection%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20merge%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20contourInterval%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20fileFormat%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20resolution%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20status%0A%20%20%20%20%20%20%20%20%20%20%20%20dateCreation%0A%20%20%20%20%20%20%20%20%20%20%20%20downloadPath%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D)

```
query GetExports{
  node(id:"MapPlan:5a0de0835f1e08eaabc732bd"){
    ... on MapPlan{
      exports(first:5){
        edges {
          node {
            id
            user{
              username
            }
            parameters {
              projection
              merge
              contourInterval
              fileFormat
              resolution
            }
            status
            dateCreation
            downloadPath
          }
        }
      }
    }
  }
}
```

This returns the data:

```
{
  "data": {
    "node": {
      "exports": {
        "edges": [
          {
            "node": {
              "id": "Export:5ab165f348273300019b14a3",
              "user": {
                "username": "example@dronedeploy.com"
              },
              "parameters": {
                "projection": 3857,
                "merge": true,
                "contourInterval": null,
                "fileFormat": "GEOTIFF",
                "resolution": 0
              },
              "status": "PROCESSING",
              "dateCreation": "2018-03-20T19:50:11.523000+00:00",
              "downloadPath": null
            }
          }
        ]
      }
    }
  }
}
```

## Checking the status of an Export

If you want to keep checking back on the status of a given export you can use the same query shown in Fetching a Single Object to get it.

```
query GetExport{
  node(id:"Export:5ab165f348273300019b14a3"){
    ... on Export{
      status
      downloadPath
    }
  }
}
```


# Creating an Export

Our APIs are not just for viewing data, you can also create data with [mutations.](http://graphql.org/learn/queries/#mutations)

For these examples you will need to substitute your own Plan IDs.

The easiest way to try these APIs is to use the [API Explorer](https://www.dronedeploy.com/graphql?operationName=null\&query=mutation%7B%0A%20%20createExport\(input%3A%7BplanId%3A%20%22MapPlan%3A5a0ddee5a6b7d90aecdc2f1d%22%2C%20parameters%3A%7Blayer%3AORTHOMOSAIC%7D%7D\)%7B%0A%20%20%20%20export%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A\&variables=). This has useful features like autocomplete (ctrl+space) and query/input validation.

```
mutation{
  createExport(input:{planId: "MapPlan:5a0ddee5a6b7d90aecdc2f1d", parameters:{layer:ORTHOMOSAIC}}){
    export{
      id
    }
  }
}
```

Here the createExport mutation takes an input of `planId` and `parameters`. In parameters only the `layer` is required.

This will create the export and then query for the exports id in the response:

```
{
  "data": {
    "createExport": {
      "export": {
        "id": "Export:5ab169ed8904ec000136eac9"
      }
    }
  }
}
```

You can then use the steps in [Fetching Exports](/api/examples/fetching-exports) to check on the status of that export.

## Using Variables

As the input gets more complex you will want to use GraphQL variables. For some background information on Variables in Mutations, [see here](http://graphql.org/learn/queries/#variables).

To take the query above and use variables you need to do 3 things:

1. Define the variable in the mutation signature:

   > `mutation($input:CreateExportInput!){`
2. Use the defined variable in the mutation:

   > `createExport(input:$input){`
3. Define the value of the variable in the `variables` section of the JSON payload

[This transforms the query to the following:](https://www.dronedeploy.com/graphql?operationName=null\&query=mutation\(%24input%3ACreateExportInput!\)%7B%0A%20%20createExport\(input%3A%24input\)%7B%0A%20%20%20%20export%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A\&variables=%7B%0A%20%20%22input%22%3A%7B%0A%20%20%20%20%22planId%22%3A%20%22MapPlan%3A5a0ddee5a6b7d90aecdc2f1d%22%2C%0A%20%20%20%20%22parameters%22%3A%20%7B%0A%20%20%20%20%20%20%20%20%22layer%22%3A%20%22ORTHOMOSAIC%22%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D)

```
mutation($input:CreateExportInput!){
  createExport(input:$input){
    export{
      id
    }
  }
}
```

With the variables:

```
{
  "input":{
    "planId": "MapPlan:5a0ddee5a6b7d90aecdc2f1d",
    "parameters": {
        "layer": "ORTHOMOSAIC"
    }
  }
}
```

The raw request looks like:

```
Authorization: Bearer <api_key>
POST /graphql
{
  "query": "mutation CreateExport($input:CreateExportInput!){createExport(input:$input){export{id}}}",
  "variables": {
    "input": {
      "planId": "MapPlan:5a0ddee5a6b7d90aecdc2f1d",
      "parameters": {
        "layer": "ORTHOMOSAIC"
      }
    }
  }
}
```


