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’). |
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
- 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
- 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:
- 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.
- 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:
- 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.
- 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).
- 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.
- 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: