NAV
NOTE: The v2 API described in this document is currently in BETA. Documentation, SDKs, and guides are still under development. Take care to only use APIs marked as stable.
shell

Getting Started

Here’s an example call made to the helpdesk/discover endpoint:

curl http://example.com/api/v2/helpdesk/discover

Example response:

{
    "data": {
        "is_deskpro": true,
        "helpdesk_url": "https:\/\/example.com\/",
        "base_api_url": "https:\/\/example.com\/api\/v2\/",
        "build": "1477995658"
    },
    "meta": {},
    "linked": {}
}

The DeskPRO API is a REST-based API that runs over HTTP(S). All API requests are made to a URL that begins with http://example.com/api/v2/.

Since all API requests are simply HTTP requests, it’s easy to use in any programming language. For the purposes of demonstration, we’ll use cURL in our examples here.

API Browser

On any DeskPRO instance, browse to /api/v2/doc to view a full auto-generated API browser.

For example, http://example.com/api/v2/doc.

The auto-generated API browser can help if you need to quickly locate a particular API or if you want to see metadata about a particular API endpoint (such as tags, versions or stability flags).

Authentication

curl -H "Authorization: key 2:YWK2PGCS8CNW62SR8TBTBKWMY" \
    http://example.com/api/v2/me

Example response:

{
    "data": {
        "auth_method": "api_key",
        "app_id": null,
        "person_id": 1,
        "person": {
            "id": 1,
            "...": "..."
        }
    },
    "meta": {},
    "linked": {}
}

The above example is one of the few API endpoints that is public. Almost every API endpoint in DeskPRO that is actually useful requires authentication. The most common way to use the API is via an API key. An admin can create keys from Admin > Apps > API Keys.

To authenticate an API request, you send an Authorization header like Authorization: key YOURKEY. Your API key will be an integer, followed by a colon, followed by a long random string of characters.

Example request to the /me endpoint to see info about the agent the key is assigned to:

API Versions and Backwards Compatibility

API request without a version prefix (always using the latest API version)

curl -H "Authorization: key 2:YWK2PGCS8CNW62SR8TBTBKWMY" \
    http://example.com/api/v2/me

API request with a version prefix

curl -H "Authorization: key 2:YWK2PGCS8CNW62SR8TBTBKWMY" \
    http://example.com/api/v2/20161122/me

The major API version is version 2, as denoted by the path prefix /api/v2/. But you may also specify a hard-coded date in the format of YYYYMMDD to guarantee API compatibility for that date.

Examples:

If you do NOT specify a date segment (such as the last example above), then the API endpoint you use will always be the latest.

We guarantee that the API for a particular version will remain compatible, even if you upgrade DeskPRO.

This means that the “shape” of JSON payloads (both input requests and output responses) will remain the same. Though we may make additions which are optional and do not change the overall behaviour of the API.

For example, we might add a new input parameter to PUT /tickets for a new feature. But if your application code doesn’t submit this parameter, then it doesn’t matter; the API would just function the way it always did. This is an example of an API change that is backwards compatible and as such it would not constitute a breaking change and we would not create a new API version for it.

In rare cases, we may need to make a breaking change (for example, to fix a bug that affects actual behaviour). In those cases a new API version will be created. If you are using the API with a version prefix as described above, then you will continue to use the old version and no changes will be required in your application. But if you are not using a version prefix (which means you are always using the “latest API”), then it’s possible a breaking change will require you to update your code.

API Endpoint Stability

Note that some API endpoints are marked as unstable in the API browser. Unstable APIs means they may change without warning, and without a new API version being issued.

This means that if you are using an unstable API, upgrading DeskPRO may result in that API being changed in a backwards-incompatible way without notice.

These APIs are generally APIs intended for internal use, or are otherwise experimental. If you intend to use an unstable API, you should submit a ticket to support@deskpro.com requesting the API become stable.

Request Format

The DeskPRO API is completely JSON.

HTTP Verbs

The HTTP verb you use is meaningful. Here’s a summary of the HTTP verbs you can use with the DeskPRO API and what they mean:

Verb Description Example
GET Get a single resource or collection GET /tickets or GET /tickets/13
DELETE Delete a single resource DELETE /ticket/13
PUT Create something new PUT /tickets
POST Update an existing resource POST /tickets/13

Response Format

When you perform a GET request to load a resource or a collection, you’ll get a response like this.

{
    "data": {},
    "links": {},
    "meta": {}
}

Collection Responses

Example request to /tickets which is a collection resource:

curl -H "Authorization: key 2:YWK2PGCS8CNW62SR8TBTBKWMY" http://example.com/api/v2/tickets

Example response of a collection resource

{
   "links": {
        "first": "/tickets",
        "next": "/tickets?page=2",
        "prev": null,
        "last": "/tickets?page=106"
   },
   "data": [
      {
        "id": 1,
        "person_id": 4,
        "subject": "Foo Bar",
        "...": "..."
      },
      {
        "id": 2,
        "person_id": 12,
        "subject": "Fizz Buzz",
        "...": "..."
      }
   ],
   "meta": {
      "total": 5445,
      "page": 1,
      "per_page": 10,
      "total_pages": 545
   }
}

Example fetching ticket objects for 3 specific ticket IDs

curl -H "Authorization: key 2:YWK2PGCS8CNW62SR8TBTBKWMY" \
    http://example.com/api/v2/tickets?ids=123,456,789

During a resource collection request, you can specify the following optional query parameters:

Collection responses are always an array of objects inside of data.

links will contain some useful links to help you paginate:

meta will contain some useful data:

Tip: Most collections accept a ids parameters

Most collection resources accept an ids parameter where you can provide specific IDs for resources you want to retrieve. This makes it easy to load multiple objects at once.

Creating and Updating Content

When you update a resource with POST, the API will simply return a 204 No Content empty response to acknowledge that the request succeeded. When you create a resource with a PUT request, the API will return a 201 Created response.

In both cases, a Location header will be supplied with the full URL to the API endpoint where you can GET the resource.

TIP: If you would rather your POST/PUT request return the full resource automatically (i.e. you want to use it right away), you can submit your request with the ?follow_location=1 query string parameter. This will cause the API to return the resource as if you did the GET yourself.

Common HTTP Status Codes

The HTTP status codes that the API returns is significant. Here is a list of common return codes.

Code Verbs Example
200 GET found and returned
404 Any resource not found
201 POST created resource
204 PUT updated resource
400 Any Bad Request
401 Any unauthorized
403 Any forbidden
405 Any method not allowed
429 Any too many requests
423 Any Locked

API Key Limits

You can specify API limits on every API key you create. For example, it is not uncommon to set an upper limit on an API key to prevent some kind of mistake in it’s use (such as a flood or infinite loop situation). You can define these limits in terms of an hourly limit or a daily limit.

For cloud customers, there is also default global limit to prevent abuse. You can raise this on request by contacting us at support@deskpro.com.

When you hit a rate limit, requests will begin to fail with a HTTP status code 429 Too Many Requests error.

Error Responses

{
    "status": 400,
    "code": "invalid_json_body",
    "message": "Invalid JSON body"
}

Error responses are also JSON and follow the shape described here.

Detailed Errors

{
    "status": 400,
    "code": "invalid_input",
    "message": "Request input is invalid.",
    "errors": {
        "errors": [
            {
                "code": "extra_fields",
                "message": "Unexpected field names: name"
            }
        ],
        "fields": {
            "email": {
                "errors": [
                    {
                        "code": "required",
                        "message": "This value should not be blank."
                    }
                ]
            },
            "date": {
                "errors": [
                  {
                    "code": "invalid_date",
                    "message": "This date is invalid"
                  }
                ],
                "fields": {
                  "day": {
                      "errors": [
                        {
                          "code": "out_of_range",
                          "message": "Must be a number between 1 and 31"
                        }
                      ]
                  },
                  "year": {
                    "errors": [
                      {
                        "code": "required",
                        "message": "This value is required"
                      }
                    ]
                  }
                }
            }
        }
    }
}

In some cases, detailed error messages are available, such as when there are form validation errors.

The root errors property is an object that has two properties:

API Token Exchange

Example request sending login credentials

curl -H "Content-Type: application/json" \
     -X POST \
     -d '{"email": "user@example.com", "password": "my_password"}'
     http://example.com/api/v2/api_tokens

Example response with an API token

{
    "data": {
        "person_id": 1,
        "token": "18:BZWWGQ58QDX8H5B4W4RAJ978Q"
    },
    "meta": {},
    "linked": {}
}

The /me endpoint returns info about the agent account the token/api key is for

curl -H "Authorization: token 18:BZWWGQ58QDX8H5B4W4RAJ978Q" \
    http://example.com/api/v2/me

Example response:

{
    "data": {
        "auth_method": "api_token",
        "app_id": null,
        "person_id": 1,
        "person": {
            "id": 1,
            "...": "..."
        }
    },
    "meta": {},
    "linked": {}
}

You can also use the API to exchange an agent login for an API token which can be used to authenticate requests. An API token is similar to an API key except that it doesn’t need to be created by an admin. It’s created by the system when given a successful set of credentials.

A token is used in the same way except the Authorzation header looks like Authorization: token YOURTOKEN. This is the same as the API key method except it starts with the word “token” instead of “key”.

POST /api_tokens

Param Description Example
email Email address or username user@example.com, my_username
password Plaintext password mypassword

External Authentication Sources

Request user sources used for agents:

curl http://example.com/api/v2/api_tokens/user_sources/agent

Example response including a Google+ user source: You could then render a button “Google+ Sign-In” which loads the login_url when clicked

{
    "data": [
        {
            "id": 5,
            "title": "Google+ Sign-In",
            "type": "agent",
            "source_type": "googleplus",
            "display_type": "social",
            "display_order": 0,
            "display_options": {
                "login_url": "http:\/\/example.com\/api\/v2\/api_tokens\/user_sources\/5\/login?format=default"
            },
            "is_enabled": true
        }
    ],
    "meta": {},
    "linked": {}
}

The above example works for DeskPRO-based logins or form-based logins where a username/email address and password can be gathered from the user and then passed directly to the API for validation. But it does NOT work for other types of authentication where we need to send the user off to some external site (e.g. JWT, SAML, oAuth, Google+, Facebook, etc).

For these types of apps, you need to render a website with a special URL for the user to log in to. When the user finishes logging in, they are redirect back to DeskPRO which can then communicate the changes up to your app through Javascript.

Typically, the first step in your app will be to get a list of usersources that exist so you can render some kind of button for external usersources.

Handling External Login

In your app, you would render a button that loaded the URL in the data.display_options.login_url field. In a web app, this might be rendering an <a> tag for example. In a desktop or mobile application, you would initialise a new web view to accept te login.

After the user logs in, they are returned to DeskPRO which renders a special page like this:

After a user successfully logs in on the remote site, they are redirected back to DeskPRO which renders this special script in your webview:

<script>sendPayload({
    "token": "18:BZWWGQ58QDX8H5B4W4RAJ978Q",
    "person_id": 1
})</script>

Your app will need to make sure the web view implements this special sendPayload function so it can accept the Javascript object.

Batch Requests

Example request using a key-value map of requests to execute in a batch:

curl -H "Authorization: key 1:CVRRGQ58QDX8H5B4W4RAJ978Q" \
     -H "Content-Type: application/json" \
     -X POST \
     -d '
 {
     "t": {
         "method": "POST",
         "url": "/api/tickets",
         "payload": {
             "title": "new-ticket"
         }
    },
    "john": "/api/people/1",
    "img": "/api/people/1/image",
    "parts": "/api/tickets/5/participants"
 }
'
     http://example.com/api/v2/batch

Example response where each response uses the same key you sent in the request:

{
    "t": {
      "headers": {
          "response_code": 201,

      },
      "data": {
         "title": "new-ticket"
         "...": "..."
      }
    },
    "john": {
        "headers": {
          "response_code": 404
        },
        "data": {
          "...": "..."
        }
    },
    "...": "..."
}

Sometimes you want to perform multiple queries all at once. For example, maybe you need to load a few collections to populate a form. Normally you would need to submit multiple HTTP requests which could be slow.

You POST a map to the /batch endpoint describing the requests you want to submit. The system will process all of your requests at once, and send you back a single result object. The keys of the result will be the same keys you submitted.

POST /batch

Post an object/map (top-level) with the following schema:

Property Description Example
Note: KEY Any arbitrary string you want to use to identify the request. req_1, department_info, foobar, 12
KEY.url The API endpoint you want to call. You can also specify query-string params here. /api/v2/me, /api/v2/tickets?page=2
KEY.method (optional) GET, POST, DELETE, PUT. Defaults to GET. GET
KEY.payload (optional) When using POST/PUT, this is the JSON object you want to submit as the payload itself. {"foo": "bar"}

Short GET Syntax

You can also use the short GET syntax to process multiple GET requests all at once by specifying multiple get[KEY]=endpoint_path parameters.

GET /batch

Param Description Example
Note: KEY The ‘key’ in get[KEY] can be any arbitrary string. It serves the same purpose as KEY above in the POST version of batch.
get[KEY] The API endpoint to fetch /api/v2/me, /api/v2/tickets

If you need to specify parameters for any of the get[KEY] calls (for example, to specify a page number), you can use the extended syntax.

Example GET call Note: For purposes of readability, the URL has been split on multiple lines.

curl -H "Authorization: key 1:CVRRGQ58QDX8H5B4W4RAJ978Q" \
    http://example.com/api/v2/batch/api/v2/batch?
        get[stars]=/api/v2/ticket_stars
        &get[departments]=/api/v2/ticket_departments

Here’s an example where the endpoint contains parameters. You need to encode ’?’ and ’&’ so they don’t get read by the main batch request itself.

curl -H "Authorization: key 1:CVRRGQ58QDX8H5B4W4RAJ978Q" \
    http://example.com/api/v2/batch/api/v2/batch?
        get[stars]=/api/v2/ticket_stars
        &get[tickets]=/api/v2/tickets%3Fpage%3D2%26ids%3D1%2C2%2C3%2C4

# the last line decodes to a URL like:
# /api/v2/tickets?page=2&ids=1,2,3,4

Side Loading

Example ticket response without side loading

curl -H "Authorization: key 1:CVRRGQ58QDX8H5B4W4RAJ978Q" \
    http://example.com/api/v2/tickets/123

Example response. Notice how we have IDs for various relationships such as the person, agent or department.

{
    "data": {
        "id": 123,
        "ref": "XXXX-0028-IOCC",
        "department": 20,
        "person": 59080,
        "agent": 2,
        "status": "awaiting_user",
        "subject": "Example Ticket"
    },
    "meta": [],
    "linked": []
}

Example WITH sideloading on department and person

curl -H "Authorization: key 1:CVRRGQ58QDX8H5B4W4RAJ978Q" \
    http://example.com/api/v2/tickets/123?include=department,person

Example response with sideloaded objects

{
    "data": {
        "id": 123,
        "ref": "XXXX-0028-IOCC",
        "department": 20,
        "person": 59080,
        "agent": 2,
        "status": "awaiting_user",
        "subject": "Example Ticket"
    },
    "meta": [],
    "linked": {
        "department": {
            "20": {
                "id": 20,
                "title": "Support"
            }
        },
        "person": {
            "2": {
                "id": 2,
                "name": "John Doe",
                "primary_email": "agent@example.com"
            },
            "59080": {
                "id": 59080,
                "name": "Fionna Apple",
                "primary_email": "user@example.com"
            }
        }
    }
}

Most objects in DeskPRO have other objects that are related to them. For example, a ticket has various users associated with it such as the creator, the assigned agent and any followers or CC’d users.

By default, the API will only return the IDs of these related objects and if you needed more information, you would need to use the API again to fetch the objects you wanted (for example, to get the actual title of the department a ticket was in).

However, this is tedious if you are doing it a lot. For this reason, the DeskPRO API has the idea of side-loading which instructs the API to return related objects of certain types. You do this by specifying the type of object you want to side-load in the request as a query parameter: include=type1,type2,type3.

Examples:

When you specify an include parameter, the related objects are returned in the response under the linked object. You’ll get properties like linked.TYPENAME.ID.

(Note that the actual data response stays the same. Your own app logic will need to connect the ID from the data to the object returned in the linked section.)

Access Control

Every API request is performed in the context of a specific agent or admin in the system. When you create an API key, you specify the agent account it is tied to. You can never do anything with the API that the agent/admin account would not be able to do itself through the web interface.

For example, say you made an API key for John. Using that API key, you could not view, reply, delete etc a ticket that John himself doesn’t already have access to.

This means if you needed some kind of “super” API key that could do everything, you would need to make sure the agent that key was tied to had full permissions in the helpdesk.

Access control via Tags

Every API endpoint in the system has one or more “tags” associated with it. You can view the tags for a particular endpoint by finding it in the Full API Browser. Expand the API endpoint to view the details, and under the “API tags for this endpoint” heading will be the list of tags applied to the endpoint.

For example, GET /api/v2/tickets has a tag of tickets.tickets.list. And DELETE /api/v2/tickets/{id} has a tag of tickets.tickets.delete.

You can fine-tune access to API endpoitns by specificying a tag pattern when you define the API key in Admin > Apps > API Keys. In the “Tags” tab, enter one or more tags you want to allow access to.

You can use wildcards to whitelist a whole group of related tags (indeed, the default value for API keys is to allow all API endpoints so the value is *). You can also use a minus symbol to remove specific actions you don’t want to allow.

Examples:

API Access Modes

Most of the time, most APIs are available to any authenticated user of the API. But some APIs are locked down so they cannot be used except by users accessing the API by a specific method.

You can view these limitations on each endpoint by viewing the Full API Browser. In an expanded node for an endpoint, notice the value for “Applicable API Modes”.

You almost never need to worry about this. Typically only internal APIs are marked as session or token only.