REST Hooks

The ultimate goal of any API integration is the efficient sharing of data between apps to provide greater value to your users. In order to facilitate this, an integration must provide a method to detect changes, or so-called events, that occur in the endpoint application. Currently, the two of the most popular tools for managing such events are polling and webhooks.

While polling and webhooks both accomplish the same task, webhooks are far more efficient. Zapier found that over 98.5% of polls are wasted. In contrast, webhooks only transfer data in case there is new data to send, making them 100% efficient.

REST Hooks represent a collection of patterns that treat webhooks as subscriptions. These subscriptions are manipulated via a REST API just like any other resource.

REST Hooks allow you to subscribe to certain events in actiTIME. Whenever an event you have subscribed to occurs, actiTIME will send a JSON payload to a URL that you specify, informing you of the change. For example, you can subscribe to the events such as creating a new task or modifying a time-track record.

More info on REST Hooks is available at http://resthooks.org

The following requests are supported for the operations with the subscriptions via actiTIME REST API:

GET/hooks – gets a list of subscriptions;
POST/hooks – creates a subscription;
POST/hooks/unsubscribe – deletes a subscription by ‘target_url’;
DELETE/hooks/{id} – deletes a subscription by ‘id’.

Events List

Typically, an event is an action applied to an object.

Supported actions: create, update, delete.
Supported objects: task, project, customer, time-track, time-track’s approval status, leave time, user, department, time zone group.

You can subscribe to all the events at the same time or to some certain events (for example, creating a new department, updating the task details, deleting a leave time, etc.).

The events that a user can be subscribed to are listed in the table below. All the event names are case-sensitive.

Event Subscription Description
* Subscription to all supported and available events.
create Subscription to the events of creating the supported objects.
update Subscription to the events of updating the supported objects.
delete Subscription to the events of deleting the supported objects.
task Subscription to all the events of the supported actions on the available tasks.
project Subscription to all the events of the supported actions on the available projects.
customer Subscription to all the events of the supported actions on the available customers.
timetrack Subscription to all the events of modifying the available time-track records (create / update / delete records).
timetrackApprovalStatus Subscription to all the events of changing the available time-track records’ approval statuses.
leaveTime Subscription to all the events of modifying the available leave time records (create / update / delete records).
user Subscription to all the events of the supported actions on all the users.
department Subscription to all the events of the supported actions on all the departments.
timeZoneGroup Subscription to all the events of the supported actions on all the time zone groups.
Combination of actions and objects, e.g.:
task.create, department.delete
Subscription to an event of a specified action on a specified object.
The following format must be used: “object.action”.
The ‘timetrack’, ‘timetrackApprovalStatus’ and ‘leaveTime’ objects support the combination with the ‘update’ action only but all changes of these objects (create / update / delete) will still be followed.

 

Subscription Properties

The subscription properties are listed in the table below.

Property Description
id Unique identifier of a subscription.
event Event for which a subscription is made. Case-sensitive.
See also the ‘Events List’ section.
target_url URL which the payload is sent to when an event occurs.
filter Filtering parameter. Not supported for the ‘user’, ‘department’ and ‘timeZoneGroup’ related events.
enabled Status of a subscription. Possible values: true, false.

If ‘true’, then the subscription is enabled (i.e., whenever an event occurs, the corresponding payload is sent to the ‘target_url’).
If ‘false’, then the subscription is disabled (i.e., no attempts to send the payload to the ‘target_url’ are done even if an event occurs).

lastHttpStatus The last HTTP status code returned from ‘target_url’ while trying to send the payload after an event occurs.
lastHttpError Description of the last error returned from ‘target_url’ while trying to send the payload after an event occurs.
lastHttpCall The last date when there was an attempt to send the payload to ‘target_url’.
userId Unique identifier of a user who created a subscription.

Required Permissions

  1. Any active actiTIME user can create a subscription to any of the supported events but the payload will be sent to the ‘target_url’ only if the corresponding data can be accessed via the actiTIME interfaces by the user who has created the subscription. Otherwise, no payload will be sent to the ‘target_url’ when an event occurs.The data available via actiTIME interfaces is defined by the user permissions.For example, to get the notifications about the events of changing the time-track of user X, the creator of the subscription must have the ‘Modify & Approve Other Users’ Time-Track’ permission, access to the user X and access to the tasks user X tracks time against in actiTIME.

    More info on actiTIME permissions is available in the actiTIME User Guide

  2. Any active actiTIME user with the ‘Manage Accounts & Permissions’ permission can get a full list of the subscriptions and can delete any of them.If a user does not have this permission, they can only get a list of subscriptions created by them and can delete their own subscriptions only.

Notes:

  1. When subscribed to the ‘user’ related events, the ‘username’, ’email’, ‘hired’, ‘releaseDate’ and ‘allowedActions’ properties of the users will be included into the payload only if the user who has created the subscription has the ‘Manage Accounts & Permissions’ permission at the moment an event occurs. Otherwise, only other user properties will be available in the payload.
  2. Time-track approval status info of a user X (corresponds to the ‘timetrackApprovalStatus’ event) is available to the same users who can access time-track info of the user X (corresponds to the ‘timetrack’ event).

Get List of Subscriptions

Use the following request to get a list of subscriptions with their properties:

GET/hooks

Example Request:

curl -X GET "<actiTIME URL>/api/v1/hooks" -H "accept: application/json; charset=UTF-8" -u "username:password"

Example Response:

{
    "id": 1,
    "event": "task.create",
    "filter": "projectIds=15",
    "enabled": true,
    "lastHttpStatus": 200,
    "lastHttpError": null,
    "lastHttpCall": "1641859200000",
    "userId": 1,
    "target_url": "<Target URL>"
}, {
    "id": 3,
    "event": "*",
    "filter": null,
    "enabled": true,
    "lastHttpStatus": 200,
    "lastHttpError": null,
    "lastHttpCall": 1643932800000,
    "userId": 1,
    "target_url": "<Target URL>"
}

More info on using this request is available in Swagger at the following URL:
<your actiTIME URL>/api/v1/swagger

Create Subscription

Use the following request to create a new subscription:

POST/hooks

Request body should include the following parameters:

  • event – name of an event you want to be subscribed to. Case-sensitive, optional (if not specified, then ‘*’ value is used);
  • filter – IDs of the specific entities you want to be subscribed to. Optional (if not specified, then no filter is applied);
  • target_url – target URL which you want the payload to be sent to when an event occurs. Mandatory.

Notes:

  1. Filters are supported for the selected events and related create / update / delete events only.
    Supported filters for the task events: taskIds, projectIds, customerIds.
    Supported filters for the project events: projectIds, customerIds.
    Supported filters for the customer events: customerIds.
    Supported filters for the timetrack events: userIds, departmentIds.
    Supported filters for the timetrackApprovalStatus events: userIds, departmentIds.
    Supported filters for the leaveTime events: userIds, departmentIds.Example 1:

    {
        "event": "task.update",
        "filter": {
            "customerIds": "1,2",
            "projectIds": "3,4",
            "taskIds": "10,25",
        },
        "target_url": "<Target URL>"
    }
    

    Use the filter in Example 1 to be notified about all the updates of the following tasks:

    • tasks with IDs 10 and 25;
    • tasks belonging to the projects with IDs 3 and 4;
    • tasks belonging to the customers with IDs 1 and 2.

    Example 2:

    {
        "event": "timetrack",
        "filter": {
            "userIds": "13,16",
            "departmentIds": "7,9"
        },
        "target_url": "<Target URL>"
    }
    

    Use the filter in Example 2 to be notified about all the updates of the following users’ time-track:

    • users with IDs 13 and 16;
    • users belonging to the departments with IDs 7 and 9.
  2. The following pairs of events send the same payload when a user subscribes to them (they are interchangeable):
    • ‘timetrack’ and ‘timetrack.update’
    • ‘timetrackApprovalStatus’ and ‘timetrackApprovalStatus.update’
    • ‘leaveTime’ and ‘leaveTime.update’

    These events allow you to track all the actions on objects at the same time (create / update / delete), although technically the combinations with the ‘create’ and ‘delete’ actions are not supported for the ‘timetrack’, ‘timetrackApprovalStatus’ and ‘leaveTime’ objects (for example, a subscription to the ‘timetrack.create’ event cannot be created).

  3. The different ‘target_url’-s can be registered for one event: when this event occurs, the corresponding payload will be sent to all of them.
  4. The same ‘target_url’ can be registered for different events: when these events occur, the corresponding payload will be sent to the one specified ‘target_url’.

Example Request:

curl -X POST "<actiTIME URL>/api/v1/hooks" -H "accept: application/json; charset=UTF-8" -H "Content-Type: application/json" -u "username:password" -d "{ \"event\": \"task.create\", \"filter\": { \"customerIds\": \"7\", \"projectIds\": \"13\" }, \"target_url\": \"<Target URL>\"}"

Example Response:

{
    "id": 8,
    "event": "task.create",
    "filter": "customerIds=7&projectIds=13",
    "target_url": "<Target URL>"
}

More info on using this request is available in Swagger at the following URL:
<your actiTIME URL>/api/v1/swagger

Delete Subscription

Use one of the following requests to delete a subscription:

POST/hooks/unsubscribe
DELETE/hooks/{id}

While using the POST/hooks/unsubscribe request, the ‘target_url’ of subscriptions to be deleted must be specified in the request body. After executing this request all the subscriptions with the specified ‘target_url’ will be deleted.

Example Request:

curl -X POST "<actiTIME URL>/api/v1/hooks/unsubscribe" -H "accept: application/json; charset=UTF-8" -H "Content-Type: application/json" -u "username:password" -d "{ \"target_url\": \"<Target URL>\"}"

While using the DELETE/hooks/{id} request, the ‘id’ of the subscription to be deleted must be specified. After executing this request, only the subscription with the specified ‘id’ will be deleted.

Example Request:

curl -X DELETE "<actiTIME URL>/api/v1/hooks/10" -H "accept: application/json; charset=UTF-8" -u "username:password"

For both requests the 204 status code is returned if the operation is successful. The response body is empty.

If the operation has failed, an error code is returned.

More info on using these requests is available in Swagger at the following URL:
<your actiTIME URL>/api/v1/swagger

Error Handling

When the payload is sent to the registered ‘target_url’ after an event occurs, our system will react in different ways depending on how your system responds:

  • If we get a status code which is between 200-299, then we have a successful call.
  • If we get a status code which is between 300-399 or 410 status code, then we set the ‘enabled’ property of the subscription to ‘false’ (the subscription is being disabled). If a new subscription’s event has occurred, no attempts to send the data will be made. The ‘enabled’ property of a subscription cannot be changed anymore, so you have to create a new subscription to the event if you want to get the event data again.
  • If we get a 413 status code (Too Big Payload), then we gradually reduce the number of sent events (maximum number is 1000). If 10 events are sent and we continue to get a 413 status code, then no further attempts to send this event’s data will be made. However, if a new subscription’s event has occurred, this data will be sent.
  • If we get a 500 status code, we will try to resend the data 5 times (intervals between the attempts are 5s, 30s, 5min, 30min, 1h).

It is your responsibility to make sure that the registered URL (‘target_url’) is successfully responding.

Payload Examples

The JSON payload which is sent to target URL after an event occurs includes:

  • event name (for example: create, timetrack.update, user.delete);
  • properties of an object which are usually returned via API calls (for example, properties of a task).

The data of several events can be sent in one array within the payload. Maximum number of sent events in one array is 1000.

See the examples of the payloads corresponding to the different events below.

Example for the ‘task’ event:

{
    "event.name": "task.create",
    "id": 238,
    "name": "Customer Support",
    "description": "",
    "created": 1643983841000,
    "status": "open",
    "workflowStatusId": 4,
    "typeOfWorkId": 20,
    "url": "<actiTIME URL>/tasks/tasklist.do?taskId=238",
    "projectName": "Flight operations",
    "customerName": "Big Bang Company",
    "workflowStatusName": "In Progress",
    "typeOfWorkName": "sales",
    "deadline": null,
    "estimatedTime": 6000,
    "customerId": 6,
    "projectId": 15
}

Example for the ‘project’ event:

{
    "event.name": "project.update",
    "id": 19,
    "customerId": 9,
    "name": "Accounting",
    "archived": false,
    "created": 1566950400000,
    "url": "<actiTIME URL>/tasks/tasklist.do?projectId=19",
    "customerName": "Our company",
    "description": "Cost and billing activities"
}

Example for the ‘customer’ event:

{
    "event.name": "customer.delete",
    "id": 59,
    "name": "#20 Consulting Company",
    "archived": false,
    "created": 1643984418000,
    "url": "<actiTIME URL>/tasks/tasklist.do?customerId=59",
    "description": ""
}

Example for the ‘timetrack’ event:

{
    "event.name": "timetrack.update",
    "userId": 1,
    "taskId": 136,
    "taskName": "Meetings",
    "time": 120,
    "comment": null,
    "date": "2022-02-04"
}

Example for the ‘timetrackApprovalStatus’ event:

{
    "event.name": "timetrackApprovalStatus.update",
    "userId": 1,
    "approved": false,
    "dateFrom": "2022-01-10",
    "dateTo": "2022-01-16",
    "status": "Ready"
}

Note: The ‘status’ field’s value in the ‘timetrackApprovalStatus’ event payload indicates the current status of the time-track:

  • the “NotReady” value corresponds to the ‘Not Ready for Approval’ status;
  • the “Ready” value corresponds to the ‘Ready for Approval’ status;
  • the “Rejected” value corresponds to the ‘Rejected’ status;
  • the “Approved” value corresponds to the ‘Approved’ status.

Example for the ‘leaveTime’ event:

{
    "event.name": "leaveTime.update",
    "userId": 16,
    "date": "2022-01-18",
    "leaveTypeId": 2,
    "leaveTime": 480,
    "leaveTypeName": "Time Off"
}

Example for the ‘user’ event:

{
    "event.name": "user.create",
    "id": 85,
    "active": true,
    "firstName": "John",
    "middleName": "",
    "lastName": "Smith",
    "departmentId": 9,
    "timeZoneGroupId": -1,
    "fullName": "John Smith"
}

Note: The ‘username’, ’email’, ‘hired’ and ‘releaseDate’ fields are not included into the payload.

Example for the ‘department’ event:

{
    "event.name": "department.update",
    "id": 13,
    "name": "Marketing"
}

Example for the ‘timeZoneGroup’ event:

{
    "event.name": "timeZoneGroup.delete",
    "id": 7,
    "name": "Dingolfing-Landau",
    "timeZoneId": "Europe/Berlin",
    "default": false
}

Read more about objects’ properties available via API in the following sections: