Some objects are more complex and hold higher volumes of data than the items listed above.
These objects are
- Forms- these hold your form data and can hold hundreds of thousands to millions of data rows
- Jobs - prepopulated forms that are sent to the client and filled in and returned
- Notification History - the audit and sent history for notifications that are triggered when form data arrives
For each of these types of item, retrieving data is done by posting a filter object to a URL.
Lets take retrieving form records as an example. The same principles apply to those objects where a search by filter is supplied.
An example form contains 200,000 records and we don't wish to return those all in 1 go!
Instead we utilise the Form complete record search
/api/Forms/{FormId}/CompletedRecords/search
This method takes an object as a filter in the request body and we make an HTTP POST. The full packet is as follows
{ "createdDateFrom": "2021-12-16T19:44:22.245Z", "createdDateTo": "2021-12-16T19:44:22.245Z", "uploadedDateFrom": "2021-12-16T19:44:22.245Z", "uploadedDateTo": "2021-12-16T19:44:22.245Z", "id": 0, "originalId": 0, "jobId": 0, "mobileUserId": 0, "userGroup": "string", "uploadId": "string", "fieldId": 0, "userDefinedFilter": [ {} ], "orderBy": [ { "propertyName": "string", "descending": true } ], "pagination": { "page": 2147483647, "rowCount": 2147483647 }}
You dont need to supply the full packet, you only need to specify the attributes to search on. So, to return records by a single mobile user, all you need to do is log in, add the bearer token to the header and post the following to the endpoint. You will notice that the orderBy and pagination sections are mandatory and need to be populated with sensible values
{ "mobileUserId": 18635, "orderBy": [ { "propertyName": "id" "descending": true } ], "pagination": { "page": 1, "rowCount": 500 }}
The above query will retrieve the 1st 500 records that were collected by Mobile User Id 18635. To retrieve the second batch, Page can be set to 2. You know you have got all the data available when the actual returned row count is less than the specified pagination row count for the nth page.
Similarly, to periodically retrieve batches of data you can use the below format
{ "uploadedDateFrom": "2021-12-16T19:44:22.245Z", "uploadedDateTo": "2021-12-16T19:44:22.245Z", "orderBy": [ { "propertyName": "uploadedDate", "descending": true } ], "pagination": { "page": 1, "rowCount": 100 }}
The uploadedDate(from) entry you will need to set to the latest date returned in the previous batch. It will be row 1 in the case above as we ordering that descending
So the very first time you retrieve data you may use
{ "uploadedDateFrom": "2000-01-01T00:00:00.001Z", # A very early date that predates any data in the system "uploadedDateTo": "2021-12-16T19:44:22.245Z", # Now ! "orderBy": [ { "propertyName": "uploadedDate", "descending": true } ], "pagination": { "page": 1, "rowCount": 1000 }}
For example If the first row in the returned result set you have an entry where uploadedDate = "2021-12-16T19:44:01.000Z"
Then the next request would be
{ "uploadedDateFrom": "2021-12-16T19:44:01.000Z", #The latest data returned from above "uploadedDateTo": "2021-12-16T19:59:22.245Z", # Now! (15 minutes later) than the first request "orderBy": [ { "propertyName": "uploadedDate", "descending": true } ], "pagination": { "page": 1, "rowCount": 1000 }}
The above is a simple example, if you want to get an up to the minute stream of data in an easy to use format, a better solution is to consider using Notification/WebHooks functionality or the WMConnect module
You can mix and match the attributes, you may want to return a page of records for a mobile user between 2 dates.
As well as the predefined attributes that are applicable to any form. You can also search on of the custom fields on a form, as long as the field has been designated 'Searchable' using the checkbox in the form designer.
So if you wished to do the above, but limit the results to where a field on your form (Meter Type for example) was set to 'Gas' the you could use the following construct
{ "uploadedDateFrom": "2021-12-16T19:44:01.000Z", #The latest data returned from above "uploadedDateTo": "2021-12-16T19:59:22.245Z", # Now! (15 minutes later) than the first request
"userDefinedFilter": [ {uniqueName : "MeterType", "value" : "Gas"} ],
"orderBy": [ { "propertyName": "uploadedDate", "descending": true } ], "pagination": { "page": 1, "rowCount": 1000 }}
You may also AND an unlimited number of searchable fields
"userDefinedFilter": [ {uniqueName : "MeterType", "value" : "Gas"}, {"uniqueName" : "Manufacturer", "value" : "solenvis" } ],
By specifying the field name twice, you can create an OR clause
"userDefinedFilter": [ {uniqueName : "MeterType", "value" : "Gas"}, {uniqueName : "MeterType", "value" : "Water"}, {"uniqueName" : "Manufacturer", "value" : "solenvis" } ],
Internally this is interpreted as
((MeterType = "Gas" OR MeterType = "Water") AND Manufacturer = "solenvis")