Bulk Requests
In addition to supporting operations that act on a single resource, most resources can also be actioned in bulk. These bulk requests can be used to efficiently action multiple records in a single API request and are especially useful in different data integration scenarios.
The different kinds of bulk requests supported are:
- Batch requests
- Match Update requests
- Import requests
Execution Mode
When submitting a bulk API request, the API request can specify an execution mode
query parameter to indicate how the request should be executed. A value of ?mode=AllOrNone
will run all records in the request within a single transaction and return a single response that contains a success/failure indication that applies to all the records in the request. If any record fails, none of the changes in the request will be applied.
A value of ?mode=PerRecord
will run all records in the request within their own transaction and return a single response that contains multiple success/failure indications for every record in the request. Individual records fail or succeed without affecting the outcome of the other records within the same request.
Note
If no mode
is specified, On Key defaults to AllOrNone
.
Batch Requests
The On Key API supports batch CRUD operations for most resources. A batch CRUD operation can action multiple records in a single API request.
Batch Create
When attempting to create a batch of new records for a resource, a unique identifier (also known as a userObjectId
) needs to be specified for every record in the batch. The unique userObjectId
allows On Key to associate and echo back any error condition for a specific record in the API response.
To illustrate, consider the following json
payload for creating a batch of records for the Asset Importance
resource. In this scenario, record2
does not include a description
property which violates the business rules for creating a new Asset Importance
resource.
curl -v -X POST https://{server}/api/tenants/{client}/{connection}/modules/risk/assetimportances/batch?mode=PerRecord \
-H 'Content-Type:application/vnd.onkey.entitycollection+json' \
-H 'Authorization: Bearer {accessToken}' \
-d '[{
"userObjectId" : "record1",
"properties": {
"code": "ABC",
"description": "111111",
"notes": "notes1",
"weight": 1
}
},
{
"userObjectId" : "record2",
"properties": {
"code": "DEF",
"description": null,
"notes": "notes2",
"weight": 2
}
}]'
When executing this request using ?mode=PerRecord
, the response code will be 200 OK
with the following response body:
{
"messages": [
{
"code": "Core_Data_RecordCreated",
"message": "Record successfully created",
"objectId": "1543841451656001",
"objectType": "AssetImportance",
"severity": "information",
"userObjectId": "record1"
},
{
"code": "Core_LengthValidator",
"message": "{AssetImportance->Description} must be between 1 and 100 characters. You entered 0 characters",
"objectType": "AssetImportance",
"properties": [
"AssetImportance->Description"
],
"severity": "error",
"userObjectId": "record2"
}
]
}
Notice that the userObjectId
is echoed back for both record1 and record2 to report on whether every record within the batch was successfully created or not. Also note the unique objectId
returned for the inserted record1.
The same request executed using ?mode=AllOrNone
will result in a response code of 400 Bad Request
with the following response body:
{
"messages": [
{
"code": "Core_Resources_SystemRequiredPropertyMissing",
"message": "{AssetImportance->Description} should not be missing or null",
"objectType": "AssetImportance",
"properties": [
"AssetImportance->Description"
],
"severity": "error",
"userObjectId": "record2"
}
]
}
Notice that the response now only contains the error for record2 and that record1 was not inserted due to the the execution mode of AllOrNone
.
Batch Update and Delete
To update or delete a batch of existing records, the API request needs to specify the id
and version
for every record in the batch. The id
will be used to communicate the success or failure for every record in the batch based on the execution mode
selected.
To illustrate, consider the following example for updating a batch of Asset Importance
resources.
curl -v -X PATCH https://{server}/api/tenants/{client}/{connection}/modules/risk/assetimportances/batch?mode=PerRecord \
-H 'Content-Type:application/vnd.onkey.entitycollection+json' \
-H 'Authorization: Bearer {accessToken}' \
-d '[
{
"id": 1543843155165003,
"version": 1,
"operations": [
{
"path": "description",
"value": "changed AA"
},
]
},
{
"id": 1543843155164002,
"version": 1,
"operations": [
{
"path": "description",
"value": "changed BB"
},
{
"path": "notes",
"value": "some notes update"
}
]
}]'
When executing this valid request using ?mode=PerRecord
, the response code will be 200 OK
with the following response body:
{
"messages": [
{
"code": "Core_Data_RecordUpdated",
"message": "Record successfully updated",
"objectId": "1543843155164002",
"objectType": "AssetImportance",
"severity": "information"
},
{
"code": "Core_Data_RecordUpdated",
"message": "Record successfully updated",
"objectId": "1543843155164002",
"severity": "information"
}
]
}
Notice that the objectId
is echoed back and contains the unique identity for every record processed in the batch.
An invalid request executed with ?mode=AllOrNone
will result in a 400 Bad Request
status code with the following response body:
{
"messages": [
{
"code": "Core_LengthValidator",
"message": "{AssetImportance->Description} must be between 1 and 100 characters. You entered 0 characters",
"objectId": "1543844764239005",
"objectType": "AssetImportance",
"properties": [
"AssetImportance->Description"
],
"severity": "error"
}
]
}
Notice the objectId
in the response body to indicate the record in the batch that failed.
Match Update Requests
The On Key API supports the match update of properties for a resource. A match update will update the same set of properties for a batch of records for the same resource to all have the same value (i.e. they will all match) across the different record instances.
Note
Match update is only supported for a select sub-set of properties (if any) for a resource. Use the Hypermedia associated with a resource to see if match update operation is available.
To illustrate, consider the following example for updating the description
property of the Asset Importance
resource to have the same value for two different records:
curl -v -X PATCH https://{server}/api/tenants/{client}/{connection}/modules/risk/assetimportances/matchbatch?mode=PerRecord \
-H 'Content-Type:application/vnd.onkey.entitymatchupdatecollection+json' \
-H 'Authorization: Bearer {accessToken}' \
-d '{
"records": [
{
"id": 1543843155165003,
"version": 1
},
{
"id": 1543843155165002,
"version": 3
}
],
"operations": [
{
"path": "description",
"value": "Same value for all records"
}
]
}'
As with batch requests, match update requests can be executed using either the AllOrNone
or PerRecord
execution mode. The same error mechanism used for Batch Update and Delete responses also applies to match update responses.
Import Requests
The On Key API supports a generic Import request to action (Insert
, Update
, Delete
or Merge
) different types of records within a single POST
request. The import request can be scheduled and executed asynchronously and supports the same execution mode and error handling behaviours as existing batch requests. Schema converters can be used within the request to resolve reference lookups and to uniquely identify the records to action.
Records can be grouped and executed in order by appending the optional ordered=true
query string parameter to the request uri and by assigning individual records within the request the same GroupOrder
identifier. Groups with a smaller GroupOrder
identifier are actioned first.
The Merge
action will check whether an existing record exists. If not, a new record will be created, otherwise the existing record will be updated. This is especially useful in system-to-system integration scenarios where an integration flow can be setup to synchronize data between On Key and other systems.
To illustrate, consider the following request where a single, ordered import is used to assign a Resource Trade to a staff member Resource and then set the same Resource Trade as the default for the staff member Resource:
curl -v -X PATCH https://{server}/api/tenants/{client}/{connection}/modules/system/imports?mode=PerRecord&ordered=true \
-H 'Content-Type:application/vnd.onkey.entityimportcollection+json' \
-H 'Authorization: Bearer {accessToken}' \
-d '[
{
"entityType": "ResourceTrade",
"action": "Merge",
"userObjectId": "record1",
"groupOrder": "1",
"Id": {
"converter": "ReferenceLookup",
"type": "Custom",
"properties": {
"ResourceTrade->Resource_Code": "SHBE",
"ResourceTrade->Trade_Code": "HAND"
}
},
"properties": {
"resourceId": {
"converter": "ReferenceLookup",
"code": "SHBE"
},
"tradeId": {
"converter": "ReferenceLookup",
"code": "HAND"
},
"permissionTreeId": {
"converter": "ReferenceLookup",
"code": "A20"
}
}
},
{
"entityType": "Resource",
"action": "Update",
"userObjectId": "record2",
"groupOrder": "2",
"Id": {
"converter": "ReferenceLookup",
"type": "Custom",
"properties": {
"Resource->Code": "SHBE"
}
},
"properties": {
"defaultResourceTradeId": {
"converter": "ReferenceLookup",
"type": "Custom",
"properties": {
"ResourceTrade->Resource_Code": "SHBE",
"ResourceTrade->Trade_Code": "HAND"
}
}
}
}
]'
Notice the use of the ?ordered=true
query string parameter and that the two records within the request have different groupOrder
identifiers. This ensures that the request for assigning the Resource Trade to the staff member Resource executes first. A merge
action is used to create or update the Resource Trade using Reference Lookup Schema converters to identify the staff member Resource and Trade. The second record subsequently uses the same reference lookup to find and assign the id of the Resource Trade created to the defaultResourceTradeId
of the same staff member Resource identified by the SHBE
code.
When executing this valid request using ?mode=PerRecord
, the response code will be 200 OK with the following response body:
{
"messages": [
{
"code": "Core_Data_RecordCreated",
"message": "Record successfully created",
"objectId": "1624859842827473",
"objectType": "ResourceTrade",
"severity": "information",
"userObjectId": "record1"
},
{
"code": "Core_Data_RecordUpdated",
"message": "Record successfully updated",
"objectId": "5000001002",
"objectType": "Resource",
"severity": "information",
"userObjectId": "record2"
}
]
}