SupportAPI SpecsAPI Docs
LogoDeveloper Portal

Get started

OverviewGetting StartedNotifications

Making API Requests

NB: The Actionstep API is case-sensitive. If during development and testing you do not get the expected results from an API request please check you have composed the request using the correct case, particularly when specifying property names in the message body.

Headers

Each request to an Actionstep API endpoint must include the following standard headers:

Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
Authorization: Bearer {your-access-token}

When a POST request is made from an HTML form use the Content-Type header shown below:

Content-Type: application/x-www-form-urlencoded

This means keys and values are encoded in key-value tuples separated by an & character, with an = character placed between the key and the value.

Requesting Resources

Supported Http verbs (methods) are:

GET - retrieve a resource.
POST - create a new resource.
PUT - update an existing resource.
DELETE - delete an existing resource.
OPTIONS - request the methods a resource supports.

GET, PUT, DELETE, and OPTIONS requests are idempotent, but POST requests are not, so additional care should be taken to prevent duplicate data records from being created (where applicable). In some instances Actionstep will detect and prevent duplicate records but this should not be relied upon. Requests for resources can be made on a single resource or a collection of resources.

Single Resource

To return a single resource you specify the resource's unique identifier. For example, to return a single time record you would make the following request where 10 is the time record's unique identifier.

GET /api/rest/timerecords/10

Multiple Resources

To return multiple resources in a single request specify a comma separated list of resource identifiers, for example, to return multiple time records you would make the request:

GET /api/rest/timerecords/1,2,3

Includes

Includes are a mechanism that allow the developer to side load resources related to the primary resource being requested. The goal of includes is to reduce the number of individual requests required to retrieve resource data. Some resources may utilise default includes, while most others need to be specifically requested. Includes may be built from a resource's links attributes returned as part of the response, which can be used individually or chained together to return deeply nested information.

Example returning the rate resource for a time record:

GET /api/rest/timerecords/1?include=rate

Example returning the unit resource for the rate resource for a time record:

GET /api/rest/timerecords/1?include=rate,rate.unit

NB: You must return the base resource if you also want to return a nested resource, i.e. the following would be an invalid request:

GET /api/rest/timerecords/1?include=rate.unit

Fieldsets

Fieldsets are a mechanism to either limit or inflate the number of resource attributes returned in a single response. By only requesting specific resource attributes you can return a more focused payload. This may include attributes that are not returned by default. By using the ":default" selector all default attributes are returned without having to name them individually. Similarly, the ":required" selector will return only required fields. The :default and :required selectors can be used in conjunction with one another. Additionally, developers can request specific fields on multiple resources when using an include clause.

Examples:

GET /api/rest/timerecords/1?fields=:default
GET /api/rest/timerecords/1?fields=:required
GET /api/rest/timerecords/1?fields=:default:required

Example returning just the billableHours and actualHours attributes for the resource:

GET /api/rest/timerecords/1?fields=billableHours,actualHours

Example returning all default attributes for the resource, plus the createdTimestamp for the resource:

GET /api/rest/timerecords/1?fields=:default,createdTimestamp

Example returning the startTimestamp attribute for the time records resource and the displayName attribute for the participants resource:

GET /api/rest/timerecords/1?include=owner&fields[timerecords]=startTimestamp&fields[participants]=displayName

Sorting

Sorting can be used to return resources in the required sequence. Sorting can be applied to individual resource attributes as well as to individual resource types returned when side loading resources using the includes clause. Resources are returned in ascending order by default, but can be requested in descending order with the use of a minus sign in front of the resource attribute name.

Example returning time records resources sorted by descending start time and then by ascending owners:

GET /api/rest/timerecords?sort=-startTimestamp,owner

Example returning time records sorted by start time and owners sorted by their display name:

GET /api/rest/timerecords?include=owner&sort[timerecords]=startTimestamp&sort[participants]=displayName

Paging

Paging can be used to navigate through a collection of resources in an efficient manner. The page keyword is used select the required page number. The pageSize keyword is used to specify the size of a page. Each resource has a default page size and a max page size (200) attribute.

Example returning page 2 of the time records resource:

GET /api/rest/timerecords?page=2

Example returning a custom page size for the time records resource:

GET /api/rest/timerecords?pageSize=100

Filtering

Filter options can be appended to the end of the request query string uri as a collection of key/value pairs. A wide range of filter operators are available and requests are constructed by appending an operator to the end of the resource field name together with the required operand.

The format can thus be represented as:

GET /api/rest/{resource}?{field name}{operator}={operand}

For example, this request will return all matters (actions) whose id is greater than 64.

GET /api/rest/actions?id_gt=64

Strict matching of field name to a specified value is also supported, for example:

GET /api/rest/actions?id=126
GET /api/rest/actions?status=closed

Below is a list of the available filter operands.

FilterOperatorExample
Equal_eq/api/rest/actions?status_eq=Active
Not Equal_nteq/api/rest/actions?status_nteq=Closed
In_in/api/rest/actions?actionType_in=1,2,3,4
Not In_ntin/api/rest/actions?actionType_ntin=2,4
Greater Than_gt/api/rest/timeentries?billableAmount_gt=5000
Less Than_lt/api/rest/timeentries?billableAmount_lt=500
Greater Than or Equal to_gteq/api/rest/timeentries?billableAmount_gteq=500
Less Than or Equal to_lteq/api/rest/timeentries?billableAmount_lteq=2500
Like_like/api/rest/actions?name_like=*Property
ILike_ilike(case insensitive variant of the Like operator)
Not Like_ntlike/api/rest/actions?name_ntlike=Commercial*
Not ILike_ntilike(case insensitive variant of the Not Like operator)

Filtering on Linked Resources

To filter on linked resources you can either filter on the primary key of the linked resource (which is the id field), or by specifying a specific resource name.

Example returning the collection of time entries associated with the specified owner (participant) whose id is 76. These two requests are equivalent.

GET /api/rest/timeentries?owner_eq=76
GET /api/rest/timeentries?owner[id_eq]=76

Example returning time entries whose owner (participant) has the last name of Jones:

GET /api/rest/timeentries?owner[lastName_eq]=Jones

Example returning time entries whose costRate is greater than 200.

GET /api/rest/timeentries?rate[costRate_gt]=200

Filtering on Sublinked Resources

Filtering can be extended beyond top level linked resources down to deeper levels.

For example, return all actions (matters) associated with any division that contains a participant whose display name ends with the word Corporation:

GET /api/rest/actions?division[participant][displayName_ilike]=*corporation

Filter Options By Field Data Type

The underlying data type of a field determines the available filter options that can be applied to that field. The 5 current field data types are; Integer, Char, Varchar, Numeric, and Datetime. The following table shows which filtering operator can be applied to each field data type.

EqualNot EqualInNot InGreater ThanLess ThanGreater Than Equal ToLess Than Equal ToLikeiLikeNot LikeNot iLike
CharYesYesYesYes
DatetimeYesYesYesYesYesYes
IntegerYesYesYesYesYesYesYesYesYes
NumericYesYesYesYesYesYesYesYes
VarcharYesYesYesYesYesYesYesYes

Using the Filter Directive

As a futher filtering option, you can append a SQL-like query string to the filter directive.

Example returning all matters (actions) whose status is active and whose priority is greater than zero:

GET /api/rest/actions?filter=status ilike '%active%' AND priority > 0

Which should look like the following once URL-encoded:

GET /api/rest/actions?filter=status+ilike+'%25active%25'+AND+priority+%3E+0

Creating Resources

Creating a new resource is achieved by making a POST request to the resource endpoint and specifying a message body in JSON format. You can create a single resource or multiple resources (of the same resource type) in a single POST request. For example:

POST /api/rest/timerecords

{
    "timerecords" :
    {
        "startTimestamp" : "2014-06-23T13:45:00+13",
        "actualHours" : "12.6",
        ...
        "links" :
        {
            "action" : "2960",
            "rate : "4"
        }
    }
}

Example creating multiple resources:

POST /api/rest/timerecords

{
    "timerecords" :
    [
        {
            "startTimestamp" : "2014-06-23T13:45:00+13",
            "actualHours" : "12.6",
            ...
            "links" :
            {
                "action" : "2960",
                "rate : "4"
            }
        },
        {
            "startTimestamp" : "2014-08-01T11:23:00+13",
            "actualHours" :  "2.8",
            ...
            "links" :
            {
                "action" : "7384",
                "rate : "2"
            }
        }
    ]
}

Use the links section to set references (foreign keys) to other resource records. In the example above we are setting the matter to which the time records are associated together with a reference to the applicable rate.

Updating Resources

Updating an existing resource is achieved by making a PUT request to the resource endpoint and specifying a message body in JSON format. You can update a single resource or multiple resources (of the same resource type) in a single PUT request.

PUT /api/rest/timerecords/10

{
    "timerecords" :
    {
        "id" : "10",
        "actualHours" : "2.6",
        ...
        "links" :
        {
            "rate" : "5"
        }
    }
}

Example updating multiple resources:

PUT /api/rest/timerecords/10,42

{
    "timerecords" :
    [
        {
            "id" : "10",
            "actualHours" : "2.6",
            ...
            "links" :
            {
                "rate" : "5"
            }
        },
        {
            "id" : "20",
            "actualHours" : "4.3",
            ...
        }
    ]
}

Use the links section to set references (foreign keys) to other resource records. In the example above we are updating the rate for the time record.

Deleting Resources

Deleting an existing resource is achieved by making a DELETE request to the resource endpoint. You can delete a single resource or multiple resources (of the same resource type) in a single DELETE request. When a resource is successfully deleted the response will be a 204 No Content http status code.

DELETE /api/rest/timerecords/10

DELETE /api/rest/timerecords/10,42

Uploading Documents (Files)

Uploading files is a multiple-step process. First you must upload the file using the Files resource endpoint in 5MB (5242880 bytes) chunks (or in 1 chunk if less than or equal to 5MB). This will return an identifier which is used in a regular PUT/POST request for any field which is of type file.

When using the files resource to upload a file the Content-Type header must be set to "multipart/form-data; boundary=[somerandomstring]"

POST /api/rest/files?part_count=1&part_number=1

Content-Length: 173773
Content-Type: multipart/form-data; boundary=---------------somerandomstring1233243324

---------------somerandomstring1233243324
Content-Disposition: form-data; name="file"; filename="hello-world.pdf"
Content-Type: application/octet-stream

{first 5mb of binary data goes here}
---------------somerandomstring1233243324--

The response from the files endpoint:

{
    "files" :
    {
        "id" : "YWY1NzVlMjkyMDc1ZjQzNmZhZjJjY2EzNDZiZDc4ZDljYzdkZWY4OWQ5MGU4",
        "status" : "Uploaded"
    }
}

Create an Email Attachment with the Uploaded File

Until the uploaded file is assigned to a resource its name is set to the returned id (shown above). When, for example, you attach the uploaded file to an email you also need to specify the name you want to give the file, and include this at the end of the fileIdentifier attribute (see example below).

POST /api/rest/emailattachments

{
    "emailattachments" :
    {
        "contentDisposition" : "attachment",
        "displayName" : "hello-world.pdf",
        "fileIdentifier" : "YmEzYzlmOWFjMDYwMTA1NzdkZTE5YzM2NjIzMjI5NzRhOWNmMGQzMzIyY2Uz;hello-world.pdf",
        "links" :
        {
            "email" : "1400"
        }
    }
}

Further detailed information on uploading and downloading files can be found here.