.. _changetracking: Change Tracking --------------- The change tracking facility allows clients to keep up-to-date with state changes in the FieldAware application. It reports creation of new entities, updates to existing entities, and deletion of entities. These changes may be caused through webapp usage, manipulation on the mobiles, or different API clients. The change tracking API provides a feed of change events. Each event listing what happened to the entity (whether it was created, updated or deleted), the time the change occurred, and from which user account the change was made. It also includes information about the entity, such as its identifier, the type of entity it is, and the URL for that entity. In the future we may include the fields that were changed as well. Currently the list of business objects that are tracked include **jobs**, **web quotes**, **field quotes**, **items**, **tasks**, **customers**, **locations**, **contacts**, **assets**, **invoices**, **users**, **unavailable times**, **unavailable time types**, **working hours exceptions** Note: The Jobs endpoint returns both Job and Quote types. Note: Unavailable times will only be returned if the relevant feature is switched on The changetracking response on **job**, **field quote** and **web quote** entities contains an ``actions`` attribute which returns the assignment status changes of the object. The ``actions`` attribute on the object also includes creations of object's **tasks** and assignment changes to the object's **tasks**. For **jobs**, **field quotes** and **web quotes**, the ``status`` value of the actions attribute can be ``ASSIGNED``, ``REASSIGNED``, ``UNASSIGNED`` or ``DISPATCHED``. For **tasks**, the ``status`` can be ``CREATED``, ``ASSIGNED``, ``REASSIGNED`` or ``UNASSIGNED``. Note: A ``DISPATCHED`` action is triggered when an unassigned job is assigned, or when an assigned job moves from a ``scheduledState`` of ``tentative`` or ``confirmed`` to ``dispatched`` in the web application's Planning Mode. A job which is assigned in Planning Mode but which is kept in the ``tentative`` or ``confirmed`` scheduled state will not trigger a ``DISPATCHED`` action. There are two basic usage patterns for the change feed. 1. The first is to access the *latest* changes. This returns a page of *recent* changes. If there are few recent changes this page may be small or even empty. The page also contains a pointer to a page of slightly older changes. This allows a client to move back in history to obtain change events that are of interest. 2. A second access pattern is geared to clients that want to know about all changes since a point in time. For this, clients obtain a token denoting a logical point in time. They can then at a later point in time ask for all the changes that occurred since that point in time. If there are too many changes to fit on a page, a pointer is included to a follow-on page. In this way, a client can obtain all changes in chronological order. *NB* There are a number of known limitations to the tracking system as it stands. In particular, not all *deletes* are accurately tracked. This means that in certain circumstances, entities may be deleted without generating an event on the feed. Another current limitation is that changes to an entity that pertain only the custom fields of the entity do not generate an event on the change feed. Finally, **business** objects are not currently tracked for changes. Note to Enterprise Customers: Change tracking returns changes to all entities from all branches belonging to the parent organization, except for ``Job`` and ``User``. Changes to ``Job`` and ``User`` entities are returned if the API user associated with the auth token has view or full-access rights to the entity's branch. Latest Changes .............. .. http:get:: /changes/latest/ Get a page of the most recent changes in the system. The page contains a link to the previous set of changes, and an array of change events. Change events have an identifier. The also carry information about the entity, including at least the identifier of the entity, and its class. More fields may be returned, so it is important to be able to handle entity objects with more attributes than just *uuid*. The *status* indicates whether the entity has been created, updated or deleted. There is also an indication of when the change was made and on whose behalf the change was made. Like the entity object, the changedBy object is open-ended and may carry additional information in addition to the identifier of the user that caused the change. The page linked to, containing the older set of changes, includes a link back (i.e. forward) to the latest changes, accessed through the *nextChanges* attribute of the representation. It also contains another link further back to yet older changes, accessed through the *previousChanges* attribute. Clients can indicate the maximum *pageSize* they are willing to accept. The server will return pages that are strictly smaller than the *pageSize* indicated. **Sample request**: .. sourcecode:: http GET /changes/latest/ HTTP/1.1 Host: api.fieldaware.net Authorization: Token 9dcae3660ec84eac94bb506e09a9af40 Accept: application/json **Sample response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json Link: "https://api.fieldaware.net/changes/previous/2014-10-14/" { "items": [ { "status": "UPDATED", "changedBy": { "uuid": "3bf0cb0efb6e471b8826b59cf4748600" }, "entityClass": "Job", "changedOn": "2014-10-15T12:16:53+00:00", "url": "https://api.fieldaware.net/job/7cc5e2d8879a43829dcc07655f5ca606", "entity": { "uuid": "7cc5e2d8879a43829dcc07655f5ca606" }, "actions": [ { "entityClass": "JobTask", "status": "CREATED", "uuid": "53b68807ba3747dfa48e93d1c727957c", "url": "https://api.fieldaware.net/job/7cc5e2d8879a43829dcc07655f5ca606/task/53b68807ba3747dfa48e93d1c727957c" }, { "entityClass": "JobTask", "status": "ASSIGNED", "uuid": "53b68807ba3747dfa48e93d1c727957c", "url": "https://api.fieldaware.net/job/7cc5e2d8879a43829dcc07655f5ca606/task/53b68807ba3747dfa48e93d1c727957c" } ] "id": 63252907 }, { "status": "UPDATED", "changedBy": { "uuid": "3bf0cb0efb6e471b8826b59cf4748600" }, "entityClass": "Item", "changedOn": "2014-10-15T14:05:16+00:00", "url": "https://api.fieldaware.net/item/ed4bb67933224e6c87113cb5ba93802d", "entity": { "uuid": "ed4bb67933224e6c87113cb5ba93802d" }, "actions": [], "id": 63252961 }, { "status": "CREATED", "changedBy": { "uuid": "7faed94349a34e3f8cd87d73bb1d31e5" }, "entityClass": "UnavailableTimeType", "changedOn": "2014-10-15T16:55:41+00:00", "url": "https://api.fieldaware.net/unavailability/types/9fd6797830b146519209d176d6f6358d", "actions": [], "entity": { "uuid": "9fd6797830b146519209d176d6f6358d" }, "id": 63739452 }, { "status": "CREATED", "changedBy": { "uuid": "7faed94349a34e3f8cd87d73bb1d31e5" }, "entityClass": "UnavailableTime", "changedOn": "2014-10-15T17:02:27+00:00", "url": "https://api.fieldaware.net/user/7faed94349a34e3f8cd87d73bb1d31e5/unavailability/b14d69497ec040d0bc54f19689c6344a", "actions": [], "entity": { "uuid": "b14d69497ec040d0bc54f19689c6344a" }, "id": 63739455 }, { "status": "CREATED", "changedBy": { "uuid": "7faed94349a34e3f8cd87d73bb1d31e5" }, "entityClass": "WorkingHoursException", "changedOn": "2014-10-15T17:18:27+00:00", "url": "https://api.fieldaware.net/user/7faed94349a34e3f8cd87d73bb1d31e5/exception/53b68807ba3747dfa48e93d1c727957c", "actions": [], "entity": { "uuid": "53b68807ba3747dfa48e93d1c727957c" }, "id": 63739455 } ], "prev": "https://api.fieldaware.net/changes/previous/2014-10-14/" } :>json array items: A list of JSON objects, changed items :>json string prev: URL of a page with less recent changes **Sample changed item**: An example of a JSON object representing a changed item. .. sourcecode:: javascript { "status": "UPDATED", "changedBy": { "uuid": "3bf0cb0efb6e471b8826b59cf4748600" }, "entityClass": "Job", "changedOn": "2014-10-15T12:16:53+00:00", "url": "https://api.fieldaware.net/job/7cc5e2d8879a43829dcc07655f5ca606", "entity": { "uuid": "7cc5e2d8879a43829dcc07655f5ca606" }, "actions": [ { "entityClass": "JobTask", "status": "REASSIGNED", "uuid": "53b68807ba3747dfa48e93d1c727957c", "url": "https://api.fieldaware.net/job/7cc5e2d8879a43829dcc07655f5ca606/task/53b68807ba3747dfa48e93d1c727957c" } ], "id": 63252907 } :>json string status: Change status, one of ``CREATED``, ``UPDATED``, ``DELETED`` :>json array actions: List of actions performed during the change :>json obj changedBy: JSON object, it identifies what user causing the event :>json string entityClass: Changed entity, one of ``Job``, ``Item``... :>json string changedOn: ISO-formatted datetime capturing the time the event happened :>json string url: URL of the changed item :>json obj entity: JSON object, identity identifier :>json number id: ID of the changed item **Sample request**: .. sourcecode:: http GET /changes/latest/ HTTP/1.1 Host: api.fieldaware.net Authorization: Token 9dcae3660ec84eac94bb506e09a9af40 Accept: application/json **Sample response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "items": [], "prev": "https://api.fieldaware.net/changes/previous/2014-10-14/" } :>json array items: A list of JSON objects representing changed items :>json string prev: A url to previous changes **Sample request**: .. sourcecode:: http GET /changes/previous/2014-10-14/ HTTP/1.1 Host: api.fieldaware.net Authorization: Token 9dcae3660ec84eac94bb506e09a9af40 Accept: application/json **Sample response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "items": [], "prev": "https://api.fieldaware.net/changes/previous/2014-10-13/", "next": "https://api.fieldaware.net/changes/latest/" } :>json array items: A list of JSON objects representing changed items :>json string prev: A url to previous changes :>json string next: A url to next changes **Sample request**: .. sourcecode:: http GET /changes/previous/2014-10-13/ HTTP/1.1 Host: api.fieldaware.net Authorization: Token 9dcae3660ec84eac94bb506e09a9af40 Accept: application/json **Sample response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "items": [], "prev": "https://api.fieldaware.net/changes/previous/2014-10-12/", "next": "https://api.fieldaware.net/changes/previous/2014-10-14/" } :>json array items: A list of JSON objects representing changed items :>json string prev: A url to previous changes :>json string next: A url to next changes Get Token ......... .. http:get:: /changes/token Get a token representing the current point in time **Sample request**: .. sourcecode:: http GET /changes/token HTTP/1.1 Host: api.fieldaware.net Authorization: Token 9dcae3660ec84eac94bb506e09a9af40 Accept: application/json **Sample response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "url": "https://api.fieldaware.net/changes/63182001/", "sinceToken": 63182001 } :>json string url: URL of change feed containing events that happened *after* the point in time represented by the token :>json number sinceToken: token List Changes since Token ........................ .. http:get:: /changes/(token)/?entityClass=Task&pageSize=10&status=CREATED List all changes since the point in time represented by ``token`` Returns the same representation of the event feed as the one returned for the *latest* changes. In addition to setting the page size, clients can filter the list of changes by **entityClass**, **entityUuid** and **status**. The allowable values for the **entityClass** are *Job*, *WebQuote*, *FieldQuote*, *Item*, *Task*, *Customer*, *Location*, *Contact*, *Invoice*, *Asset*, *User*, *UnavailableTime*, *UnavailableTimeType*. For status they are *CREATED*, *UPDATED*, *DELETED*. **Sample request**: .. sourcecode:: http GET /changes/dcae3660ec84eac94/?entityClass=Task&entityUuid=d6eb1861e893477eb153a70a34604357&pageSize=10&status=CREATED HTTP/1.1 Host: api.fieldaware.net Authorization: Token 9dcae3660ec84eac94bb506e09a9af40 Accept: application/json :query entityClass: one of ``Job``, ``WebQuote``, ``FieldQuote``, ``Item``, ``Task``, ``Customer``, ``Location``, ``Contact``, ``Invoice``, ``Asset``, ``User``, ``UnavailableTime``, ``UnavailableTimeType`` :query entityUuid: a valid uuid identifier for a particular instance :query status: one of ``CREATED``, ``DELETED``, ``UPDATED`` **Sample request**: .. sourcecode:: http GET /changes/63252964/ HTTP/1.1 Host: api.fieldaware.net Authorization: Token 9dcae3660ec84eac94bb506e09a9af40 Accept: application/json **Sample response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "items": [ { "status": "UPDATED", "changedBy": { "uuid": "3bf0cb0efb6e471b8826b59cf4748600" }, "entityClass": "Customer", "changedOn": "2014-10-15T14:37:57+00:00", "url": "https://api.fieldaware.net/customer/beb65ace45ae487eb78b48729a502612", "entity": { "uuid": "beb65ace45ae487eb78b48729a502612" }, "actions": [], "id": 63252975 }, { "status": "CREATED", "changedBy": { "uuid": "3bf0cb0efb6e471b8826b59cf4748600" }, "entityClass": "Contact", "changedOn": "2014-10-15T14:44:00+00:00", "url": "https://api.fieldaware.net/contact/fec2603a5ee342d1ab32806f1856045b", "entity": { "uuid": "fec2603a5ee342d1ab32806f1856045b" }, "actions": [], "id": 63252976 }, { "status": "CREATED", "changedBy": { "uuid": "3bf0cb0efb6e471b8826b59cf4748600" }, "entityClass": "Contact", "changedOn": "2014-10-15T14:44:16+00:00", "url": "https://api.fieldaware.net/contact/782e2ca7445e4046a0efc89240e94195", "entity": { "uuid": "782e2ca7445e4046a0efc89240e94195" }, "actions": [], "id": 63252977 }, { "status": "CREATED", "changedBy": { "uuid": "3bf0cb0efb6e471b8826b59cf4748600" }, "entityClass": "Location", "changedOn": "2014-10-15T14:44:59+00:00", "url": "https://api.fieldaware.net/location/a4c566af7dcd485eb36bf1d5fd889e8b", "entity": { "uuid": "a4c566af7dcd485eb36bf1d5fd889e8b" }, "actions": [], "id": 63252978 }, { "status": "CREATED", "changedBy": { "uuid": "3bf0cb0efb6e471b8826b59cf4748600" }, "entityClass": "Location", "changedOn": "2014-10-15T14:45:40+00:00", "url": "https://api.fieldaware.net/location/f33dcb9228d74f85a58321885382f33f", "entity": { "uuid": "f33dcb9228d74f85a58321885382f33f" }, "actions": [], "id": 63252979 } ], "next": "https://api.fieldaware.net/changes/63252980/" } :>json array items: A list of JSON objects representing changes :>json string next: URL to next changes **Sample request**: .. sourcecode:: http GET /changes/63252964/?entityClass=Location HTTP/1.1 Host: api.fieldaware.net Authorization: Token 9dcae3660ec84eac94bb506e09a9af40 Accept: application/json **Sample response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "items": [ { "status": "CREATED", "changedBy": { "uuid": "3bf0cb0efb6e471b8826b59cf4748600" }, "entityClass": "Location", "changedOn": "2014-10-15T14:44:59+00:00", "url": "https://api.fieldaware.net/location/a4c566af7dcd485eb36bf1d5fd889e8b", "entity": { "uuid": "a4c566af7dcd485eb36bf1d5fd889e8b" }, "actions": [], "id": 63252978 }, { "status": "CREATED", "changedBy": { "uuid": "3bf0cb0efb6e471b8826b59cf4748600" }, "entityClass": "Location", "changedOn": "2014-10-15T14:45:40+00:00", "url": "https://api.fieldaware.net/location/f33dcb9228d74f85a58321885382f33f", "entity": { "uuid": "f33dcb9228d74f85a58321885382f33f" }, "actions": [], "id": 63252979 } ], "next": "https://api.fieldaware.net/changes/63252980/" } :>json array items: A list of JSON objects representing changes :>json string next: URL to next changes **Sample request**: .. sourcecode:: http GET /changes/63252964/?status=UPDATED HTTP/1.1 Host: api.fieldaware.net Authorization: Token 9dcae3660ec84eac94bb506e09a9af40 Accept: application/json **Sample response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "items": [ { "status": "UPDATED", "changedBy": { "uuid": "3bf0cb0efb6e471b8826b59cf4748600" }, "entityClass": "Customer", "changedOn": "2014-10-15T14:37:57+00:00", "url": "https://api.fieldaware.net/customer/beb65ace45ae487eb78b48729a502612", "entity": { "uuid": "beb65ace45ae487eb78b48729a502612" }, "actions": [], "id": 63252975 }, { "status": "UPDATED", "changedBy": { "uuid": "3bf0cb0efb6e471b8826b59cf4748600" }, "entityClass": "Location", "changedOn": "2014-10-15T14:46:06+00:00", "url": "https://api.fieldaware.net/location/f33dcb9228d74f85a58321885382f33f", "entity": { "uuid": "f33dcb9228d74f85a58321885382f33f" }, "actions": [], "id": 63252980 } ], "next": "https://api.fieldaware.net/changes/63252980/" } :>json array items: A list of JSON objects representing changes :>json string next: URL to next changes **Sample request**: .. sourcecode:: http GET /changes/63252964/?entityClass=Contact&status=CREATED HTTP/1.1 Host: api.fieldaware.net Authorization: Token d943a51d68c44ca38cab9abda20a4d18 Accept: application/json { "items": [ { "status": "CREATED", "changedBy": { "uuid": "3bf0cb0efb6e471b8826b59cf4748600" }, "entityClass": "Contact", "changedOn": "2014-10-15T14:44:00+00:00", "url": "https://api.fieldaware.net/contact/fec2603a5ee342d1ab32806f1856045b", "entity": { "uuid": "fec2603a5ee342d1ab32806f1856045b" }, "actions": [], "id": 63252976 }, { "status": "CREATED", "changedBy": { "uuid": "3bf0cb0efb6e471b8826b59cf4748600" }, "entityClass": "Contact", "changedOn": "2014-10-15T14:44:16+00:00", "url": "https://api.fieldaware.net/contact/782e2ca7445e4046a0efc89240e94195", "entity": { "uuid": "782e2ca7445e4046a0efc89240e94195" }, "actions": [], "id": 63252977 } ], "next": "https://api.fieldaware.net/changes/63252977/" } :>json array items: A list of JSON objects representing changed items :>json string next: URL to next changes **Sample request**: .. sourcecode:: http GET /changes/dcae3660ec84eac94/?entityClass=Task&pageSize=10&status=CREATED HTTP/1.1 Host: api.fieldaware.net Authorization: Token 9dcae3660ec84eac94bb506e09a9af40 Accept: application/json **Sample response**: In this case no changes have been made .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "items": [], "next": 63182001 } :>json array items: A list of JSON objects representing changes or an empty list :>json number next: A time token **Sample request**: .. sourcecode:: http GET /changes/63182001/ HTTP/1.1 Host: api.fieldaware.net Authorization: Token 9dcae3660ec84eac94bb506e09a9af40 Accept: application/json **Sample response**: In this case no changes have been made .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "items": [], "next": 63182001 } :>json array items: A list of JSON objects representing changes or an empty list :>json number next: A time token .. warning:: For Enterprise-enabled companies, change tracking returns changes to all entities from all groups (branches) belonging to the parent organization, except for Job and User. Changes to Job and User entities are returned if the API user associated with the auth token has View-Only or Full Access rights to the entity’s branch.