API Requests
On Key API calls accept JSON request bodies. Most GET
API calls allow you to specify one or more optional query parameters on the request URI.
Headers
The commonly used HTTP request headers are:
Name | Description | Example |
---|---|---|
Accept |
Specifies the acceptable request formats. Only application/json is supported. |
Accept: application/json |
Authorization |
Required to get an access token or make API calls. To make REST API calls, include the bearer token in the Authorization header with the Bearer authentication scheme |
Authorization: Bearer <Access-Token> |
Content-Type |
Specifies the request format. Required for operations with a request body. | Content-Type: application/vnd.onkey.entity+json |
Content Types
The supported content types for requests are:
Name | Description | Docs |
---|---|---|
application/vnd.onkey.entity+json |
Create a resource or execute a custom resource action using a POST request |
Link |
application/vnd.onkey.entitycollection+json |
Create a batch of records for a resource using a POST request |
Link |
application/vnd.onkey.entitypatch+json |
Update a resource or execute a custom resource action using a PATCH request |
Link |
application/vnd.onkey.entitypatchcollection+json |
Update a batch of records for a resource using a PATCH request |
Link |
application/vnd.onkey.entitydelete+json |
Delete a resource using a DELETE request |
Link |
application/vnd.onkey.entitydeletecollection+json |
Delete a batch of records for a resource using a DELETE request |
Link |
application/vnd.onkey.entitymatchupdatecollection+json |
Update properties for a batch of records of a resource to match (i.e. have same values) using a PATCH request |
Link |
application/vnd.onkey.entityexistscheckcollection+json |
Query the existence of Entities through providing entity criteria within a POST request |
Link |
application/vnd.onkey.entityimportcollection+json |
Import multiple entities using a POST request. |
Link |
application/vnd.onkey.customresourceactioncreate+json |
Create a customised resource action definition using a POST request |
Link |
application/vnd.onkey.customresourceactionupdate+json |
Update a customised resource action definition using a PUT request |
Link |
application/vnd.onkey.customtemplatecreate+json |
Create a customised template definition using a POST request |
Link |
application/vnd.onkey.customtemplateupdate+json |
Update a customised template definition using a PUT request |
Link |
Query Parameters
Note
For all GET requests On Key Query Language parameters can also be added to limit, filter, page, sort, join and parameterize the response data.
The commonly used HTTP request uri parameters are:
Area | Name | Description | Example |
---|---|---|---|
General | fcr |
Force-consistent-read flag to direct a GET API call to read data directly from the master database instead of the read replica. Use in integration scenarios where the replication lag between the master and read replica might be troublesome when creating or reading new or updated records | ?fcr=true |
Localisation | ct |
Content translate. Flag to indicate whether phrase translations should be executed on the response content data. | ?ct=true |
Localisation | langId |
On Key Language id to use for translating the response data. | ?langId=1001 |
Localisation | lang |
On Key Language code to use for translating the response data. | ?lang=en |
Customisations | cid |
Customisation id to use when loading the response data. | ?cid=42 |
Customisations | mergeFilter |
Flag to merge or replace a resource customisation filter with the filter specified on the query string. Defaults to true if not specified. |
?mergeFilter=false |
Asynchronous Requests | async |
Flag to enqueue the request for asynchronous execution using a Background Task |
?async=true |
Asynchronous Requests | description |
Description to use for the asynchronous Background Task |
?description=user_rights_calculation |
Asynchronous Requests | priority |
Numeric value to prioritise the execution of the asynchronous request | ?priority=150 |
Scheduled Requests | schedule |
Cron expression to schedule the asynchronous execution of a request using a Scheduled Background Task . |
?schedule=0 22 * * 5 will create a schedule with entries that trigger at 22:00 every Friday evening |
Scheduled Requests | from |
Date and time at which the schedule for the asynchronous execution of the Scheduled Background Task must start. If no value is provided the current UTC is used. |
?from=2020-05-31T12:00:00Z |
Prepared Queries | preparedQuery |
Flag to create a prepared query for paging through large sets of data | ?preparedQuery=true |
Prepared Queries | preparedQueryMaxBatchSize |
Maximum amount of records to include in the record set created for a prepared query | ?preparedQueryMaxBatchSize=5000 |
Bulk Requests | mode |
Mode in which to execute the request:
|
?mode=PerRecord |
Asynchronous Requests
By default, all On Key API requests are executed synchronously which implies that consumers block until the request has been processed. Most POST
,PUT
,PATCH
and DELETE
requests can however also be executed asynchronously.
Note
Asynchronous API requests are not supported for any GET
requests
By appending the ?async=true
query string parameter, instead of synchronously blocking until the request completes, On Key will register the request as a Background Task
and return a unique request identifier. This request identifier supports a Request-Acknowledge-Poll pattern whereby the consumer can poll On Key for progress updates on the background execution or alternatively cancel the asynchronous operation represented by the request identifier.
When submitting an asynchronous API request, On Key will respond with a 202 Accepted
status code and include the request identifier using the OnKey-Request-Id
header. It will also provide the polling uri to use for checking the background execution status of the request using the OnKey-Request-Location
header.
HTTP/1.1 202 Accepted
OnKey-Request-Id: 1584247614480001
OnKey-Request-Location: api/tenants/{client}/{connection}/BackgroundTasks/1584247614480001
When executing the polling uri, the response will contain information such as the status
, completedOn
and other progress related information for the request execution:
{
"class": "BackgroundTask",
"id": 1584247614480001,
"version": 1,
"properties": {
"createdByUserId": 500000000000,
"createdByUserFullName": "Administrator",
"createdOn": "2020-03-15T04:46:54.5011350Z",
"modifiedByUserId": 500000000000,
"modifiedByUserFullName": "Administrator",
"modifiedOn": "2020-03-15T04:46:58.7517900Z",
"completedOn": "2020-03-15T04:46:58.7517900Z",
"completedSteps": 1,
"correlationId": "0HLU8JFARMTAT:00000002",
"failedSteps": 0,
"instrumentationId": null,
"name": "user_rights_calculation",
"origin": "User",
"startedOn": "2020-03-15T04:46:55.6631980Z",
"status": "Completed",
"totalSteps": 1
}
}
Some of the values included with the response are:
Status | Description |
---|---|
status |
Status of the background task:
|
startedOn |
start date |
completedOn |
complete date |
totalSteps |
total number of steps to execute |
completedSteps |
number of steps that have completed |
failedSteps |
number of steps that have failed |
Using the above mentioned information, an API consumer can effectively determine the outcome of the asynchronous request submitted.
Request Priority
To prioritize the order in which On Key executes asynchronous requests, append a priority=<numeric value>
query string parameter (i.e.?async=true&priority=150)
to the request uri.
Note
Scheduled requests can not be prioritised and a priority specified will be ignored.
The following numeric priority ranges are supported:
Range | Values | Note |
---|---|---|
Urgent | 1-9 |
Reserved for system usage |
High | 10-99 |
High importance user requests |
Medium | 100-999 |
Medium importance user requests |
Low | >= 1000 |
Low importance user requests |
If not specified, On Key enqueues asynchronous API requests using a priority
value of 100
. As On Key executes asynchronous requests by sorting on the priority
and created_on
date for the request, an API consumer can change the order in which On Key will attempt to execute a new request by assigning a priority that is less than the priority of any of the pending/executing asynchronous requests.
Warning
Please note that request priorities should not and can not be used as a mechanism to provide order guarantees between executing different requests. It is simply a mechanism to ensure that certain requests can be prioritised and executed before others.
Scheduled Requests
Asynchronous API requests can also be scheduled for execution at a date in the future using a cron expression. Most asynchronous API requests can however only be scheduled for a single date, i.e. recurring schedules are only allowed for a small subset of API requests.
Note
Seconds are not supported within cron expressions.
On Key validates all schedules based on the capabilities for a specific API request and will prevent API consumers from creating an invalid schedule for the request. To identify if a specific API request supports a recurring or single execution schedule, inspect the uriFeatures
section of the metadata published by the documentation endpoint for the API request.
Consider the following documentation request for the CreateAssetImportance
operation on the AssetImportance
resource.
curl -v -X GET https://{server}/api/tenants/{client}/{connection}/docs/modules/risk/resources/assetimportance/action/createassetimportance \
-H 'Authorization: Bearer {accessToken}'
The request returns all the metadata for the operation which includes the uriFeatures
section shown below:
{
"type": "Create",
"name": "CreateAssetImportance",
"endpoint": {
"doc": "api/tenants/{client}/{connection}/Docs/Modules/RISK/Resources/AssetImportance/Actions/CreateAssetImportance",
"href": "api/tenants/{client}/{connection}/Modules/RISK/AssetImportances/",
"method": "POST",
"module": "RISK",
"resource": "AssetImportance",
"resourceAction": "CreateAssetImportance",
"type": "primaryAction"
},
"uriFeatures": {
"canSubSelect": false,
"canRunAsync": true,
"canSchedule": true,
"canScheduleRecurring": false,
"canFilter": false,
"canOrder": false,
"canPage": false
},
The features included within the uriFeatures
section are:
Feature | Description |
---|---|
canSubSelect |
can use OKQL $select expression |
canFilter |
can use OKQL $filter expression |
canOrder |
can use OKQL $orderby expression |
canPage |
can use OKQL $top and $skip expressions |
canRunAsync |
can execute asynchronously |
canSchedule |
can be scheduled to execute asynchronously at a single future date |
canScheduleRecurring |
can be scheduled to execute asynchronously at recurring future dates |
Scheduling
To schedule an asynchronous API request, append a schedule=<cron expression>
query string parameter (i.e.?async=true&schedule=0 22 31 5 *)
to the request uri. To configure when a recurring schedule for a request should start, include an additional from=<ISO 8601 date/time>
query string parameter (i.e. from=2020-03-31T12:00:00Z
). If no from
value is provided, On Key will start the recurring schedule for the request using the current UTC. To schedule the once-off execution of an api request on a specific date, omit the schedule
cron expression and only specify the date/time at which to execute the request using the from
query string parameter.
To further illustrate the scheduling parameters, consider the following examples:
Today | schedule |
from |
Scheduling behaviour |
---|---|---|---|
17/05/2021 |
0 22 31 5 * |
2021-06-01T12:00:00 |
Schedule the request to fire once a year at 22:00 on 31 May. Only start scheduling on 1 June 2021 which implies that the first occurence will only be on 31 May 2022 |
17/05/2021 |
0 22 31 5 * |
not set |
Schedule the request to fire once a year at 22:00 on 31 May. Start scheduling using the current UTC so given that today is 17/05/2021 , the first occurence will be on 31 May 2021 |
17/05/2021 |
not set |
2021-06-01T12:00:00 |
Schedule the request to fire once-off on 1 June 2021 at 12:00 |
Note
By default On Key predicts job schedules once a day, 7 days in advance, i.e for the next 7 days.
When executing a scheduled asynchronous request, instead of firing off the request, On Key will create a Scheduled Background Task
and use the cron expression to create Scheduled Job
entries representing the job schedule for the execution of the Scheduled Background Task
.
Once created, On Key will respond with a 202 Accepted
status code and include both the Scheduled Background Task
and unique job identifier using the OnKey-Resource-Id
and OnKey-Job-Id
custom HTTP headers. The OnKey-Job-Schedule-Location
uri header can be used to query the list of Scheduled Job
request executions whilst the OnKey-Resource-Location
header uri can be used to query the Scheduled Background Task
created.
HTTP/1.1 202 Accepted
OnKey-Job-Id: cc4820be-e990-4161-85ff-eec4bbde2acb
OnKey-Job-Schedule-Location: api/tenants/{client}/{connection}/Modules/System/Jobs/cc4820be-e990-4161-85ff-eec4bbde2acb/Schedule
OnKey-Resource-Id: 1585760985950002
OnKey-Resource-Location: api/tenants/{client}/{connection}/Modules/System/ScheduledBackgroundTasks/1585760985950002
When executing the OnKey-Job-Schedule-Location
uri, the response will contain information such as the status
, scheduledOn
, startOn
and other job related information for the scheduled job execution:
{
"class": "DomainDynamicRecord",
"id": 1585743203256507,
"properties": {
"name": "DM.DocumentRecord.Create",
"origin": "BackgroundTask",
"status": "Scheduled",
"scheduledOn": "2020-04-01T12:13:22.9016940Z",
"dispatchedOn": null,
"schedule": "0,5,10,15,20,25,30,35,40,45,50,55 * * * *",
"startOn": "2020-04-01T12:45:00.0000000Z",
"executionMode": "AllOrNone",
"requestType": "Pragma.OnKey.DM.DocumentRecords.CreateDocumentRecordRequest",
"response": null,
"backgroundTaskId": null,
"backgroundTaskName": null,
"backgroundTaskStatus": null,
"backgroundTaskStartedOn": null,
"backgroundTaskCompletedOn": null,
"backgroundTaskTotalSteps": null,
"backgroundTaskCompletedSteps": null,
"backgroundTaskFailedSteps": null
}
}
Some of the values included with the response are:
Status | Description |
---|---|
status |
Status of the Scheduled Job :
|
startOn |
date and time to dispatch on |
scheduledOn |
date and time scheduled |
dispatchedOn |
date and time dispatched |
schedule |
cron expression used to create the schedule |
response |
error if the Scheduled Job could not be dispatched |
Scheduled Execution
On Key actively monitors all the job schedules and enqueues newly triggered Scheduled Job
entries as Background Task
instances as per the normal asynchronous execution flows.
Note
By default On Key dispatches newly triggered jobs every 60 seconds.
Once On Key dispatches the request using a Background Task
, the link between the Scheduled Job
and its associated Background Task
will allow the API consumer to determine the outcome of the scheduled asynchronous request submitted. When executing the OnKey-Job-Schedule-Location
uri again, the job schedule will now contain additional Background Task
information:
{
"class": "DomainDynamicRecord",
"id": 1585743203256506,
"properties": {
"name": "DM.DocumentRecord.Create",
"origin": "BackgroundTask",
"status": "Dispatched",
"scheduledOn": "2020-04-01T12:13:22.9016940Z",
"dispatchedOn": "2020-04-01T12:40:02.9092360Z",
"schedule": "0,5,10,15,20,25,30,35,40,45,50,55 * * * *",
"startOn": "2020-04-01T12:40:00.0000000Z",
"executionMode": "AllOrNone",
"requestType": "Pragma.OnKey.DM.DocumentRecords.CreateDocumentRecordRequest",
"response": null,
"backgroundTaskId": 1585744802928007,
"backgroundTaskName": "DM.DocumentRecord.Create",
"backgroundTaskStatus": "Succeeded",
"backgroundTaskStartedOn": "2020-04-01T12:40:03.1026270Z",
"backgroundTaskCompletedOn": "2020-04-01T12:40:07.9210740Z",
"backgroundTaskTotalSteps": 1,
"backgroundTaskCompletedSteps": 1,
"backgroundTaskFailedSteps": 0
}
}
Using the above-mentioned information, an API consumer can effectively determine the outcome of any scheduled asynchronous request.
Prepared Requests
To support the performant paging through big sets of the data using GET
requests, the On Key API supports prepared queries. A prepared query is stored as an ordered set of record id's on the server side.
To create a prepared query, append the preparedQuery=true
parameter, and an optional preparedQueryMaxBatchSize=<limit>
parameter, to a GET
query string.
Tip
Always consider limiting the size of the record set for a prepared query by specifying a reasonable limit using the preparedQueryMaxBatchSize
parameter and/or by adding a $filter
segment to further narrow down the set of records.
On receiving the initial prepared query request, On Key will create an ordered set of at most <limit>
records and store the id's of these records server side. The record set will be ordered by the primary key of the resource being queried. On Key will respond by fetching and returning the first page of records along with a preparedQueryBatchId=<id>
and preparedQueryBatchSize=<available>
in the initial response. The preparedQueryBatchSize
will indicate how many records are actually available in the record set and it may be less than the requested preparedQueryMaxBatchSize
.
Note
To limit the amount of records in a single response, add a $top=<xxx>
paging fragment to your query. If the $top
is omitted, On Key will return the default page size as configured for the system.
To page through the records, append the preparedQueryBatchId=<id>
to the query string and use the the normal $top
and $skip
paging fragments to page through the data using subsequent GET
requests.
Example
To illustrate, consider the following GET
prepared query for paging through a maximum set of at most 5000 Work Order
resource records. We limit the amount of records to return in a single response to 300 by adding a $top=300
fragment:
curl -v -X GET https://{server}/api/tenants/{client}/{connection}/modules/wm/workorders?preparedQuery=true&preparedQueryMaxBatchSize=5000&$top=300 \
-H 'Authorization: Bearer {accessToken}'
After submitting the initial prepared query request, On Key will return a preparedQueryBatchId
and preparedQueryBatchSize
along with the first 300 records in the response.
{
"count": 300,
"self": {
"href": "api/tenants/{client}/{connection}/Modules/WM/WorkOrders/?preparedQuery=true&preparedQueryMaxBatchSize=5000&$top=300&$skip=0",
"method": "GET",
"type": "navigation"
},
"next": {
"href": "api/tenants/{client}/{connection}/Modules/WM/WorkOrders/?preparedQuery=true&preparedQueryMaxBatchSize=5000&$top=300&$skip=300&preparedQueryBatchId=1624602735634918",
"method": "GET",
"type": "navigation"
},
"preparedQueryBatchId": 1624602735634918,
"preparedQueryBatchSize": 5000,
"items": [
{
...
The preparedQueryBatchSize
of 5000 in the response indicates that we have 5000 records to page through. The next
hypermedia link includes a link to fetch the next 300 records. Notice that the url includes the preparedQueryBatchId
to indicate that we want to page through the same set of records that has been setup server side.
To fetch more records, we add the $top
and $skip
paging fragments along with the preparedQueryBatchId
and preparedQuery=true
to the query string of all subsequent GET
requests:
curl -v -X GET https://{server}/api/tenants/{client}/{connection}/modules/wm/workorders?preparedQuery=true&$top=300&$skip=300&preparedQueryBatchId=1624602735634918" \
-H 'Authorization: Bearer {accessToken}'
Considerations
Some important aspects to consider when using prepared queries:
- Prepared Queries only work on
GET
requests that return a pageable collection of data for resources. - The batch associated with the
preparedQueryBatchId
is stored within the database and therefore consumes server side resources. These batches are cleaned up on regular intervals (every hour) to prevent bloat server side and will therefore not be available indefinitely. - The batch of records is created at the time that the first request is made. Paging through the batch in delayed fashion will not include any new or deleted records but will include the latest information for a specific record when the page containing the record is fetched.
- Using an
$orderby
fragment on a prepared query request is not supported and will be ignored as the records are automatically ordered using the primary key of the table being paged. - The same
$filter
fragment, used to optionally scope the initial prepared query request, needs to be used across all prepared query requests. You cannot change the scope of data returned through using a different$filter
or by adding a$filter
to requests that use the samepreparedQueryBatchId
.
Schema Converters
The On Key API supports the use of a few pre-defined schema converters. Schema converters will transform properties provided within an API request after it is received, but before it is processed by the server.
Note
Some of the converters are intended to make it easier to send certain types of API requests and using them is therefore optional.
Reference Lookup Converter
A reference lookup converter automatically assigns the Id
for a lookup using a lookup strategy. Two lookup strategies are currently supported:
- Code - find the
Id
using thecode
specified for the converter - Custom - find the
Id
using the combination of property values specified for the converter
When a request with a reference lookup converter is received, the server automatically does the lookup for the reference using the converter strategy specified and, if found, automatically assigns the Id
to the property.
To illustrate, consider the following json
payload for creating an Asset Importance
resource without using a reference lookup converter.
curl -v -X POST https://{server}/api/tenants/{client}/{connection}/modules/risk/assetimportances \
-H 'Content-Type:application/vnd.onkey.entity+json' \
-H 'Authorization: Bearer {accessToken}' \
-d '{
"properties": {
"code": "HIGH",
"description": "High Importance",
"notes": "High Importance",
"weight": 1,
"permissionTreeId" : 5000000
}
}'
Notice the permissionTreeId
reference lookup property needs to be set with a value which you can get by doing separate API calls.
In data integration scenarios you often do not know the specific Id
or just want the server to figure out what the Id
is by either specifying the well-known Code
or by specifying a combination of property values to identify the entity.
Code lookup converter
The following request illustrates a json
payload to create an Asset Importance
resource using a Code
resource lookup converter to resolve the PermissionTreeId
.
curl -v -X POST https://{server}/api/tenants/{client}/{connection}/modules/risk/assetimportances \
-H 'Content-Type:application/vnd.onkey.entity+json' \
-H 'Authorization: Bearer {accessToken}' \
-d '{
"properties": {
"code": "HIGH",
"description": "High Importance",
"notes": "High Importance",
"weight": 1,
"permissionTreeId": {
"converter": "ReferenceLookup",
"type": "Code",
"code": "A20"
}
}
}'
When the request is received by the server, the server will do a reference lookup for the permissionTreeId
property and use A20
as code to automatically resolve the PermissionTree
lookup. If found, the result will be assigned to the permissionTreeId
before the server starts processing the request.
Tip
As the Code
Reference Lookup Converter is the default schema converter for the system, you can its short-hand notation by omitting the converter
and type
properties and just specify the code
If the code was not found, the request will fail.
{
"messages": [
{
"code": "Core_ValueCouldNotBeConverted",
"message": "Value specified for property {AssetImportance->PermissionTree_Id} could not be converted or resolved.",
"properties": [
"AssetImportance->PermissionTree_Id"
],
"severity": "error"
}
]
}
Custom lookup converter
The following request illustrates a json
payload to create a Warehouse
resource using a combination of Code
and Custom
resource lookup converters to resolve the different required lookups on the Warehouse
.
curl -v -X POST https://{server}/api/tenants/{client}/{connection}/modules/mm/warehouses \
-H 'Content-Type:application/vnd.onkey.entity+json' \
-H 'Authorization: Bearer {accessToken}' \
-d '{
"properties": {
"code": "CPT",
"description": "Cape Town Warehouse",
"notes": "Main warehouse in Western Cape",
"permissionTreeId": {
"converter": "ReferenceLookup",
"type": "Code",
"code": "A20"
},
"costCentreId": {
"converter": "ReferenceLookup",
"type": "Code",
"code": "065"
},
"siteId": {
"converter": "ReferenceLookup",
"type": "Custom",
"properties": {
"Site->Code": "A10",
"Site->SiteType_Code": "FAC"
}
}
}
}'
When the request is received by the server, the server will do a reference lookup for the permissionTreeId
and costCentreId
properties and use A20
and 065
as the codes to automatically resolve the PermissionTree
and CostCentre
references. It wiIll also resolve the Site
for the Warehouse
by finding a Site
with A10
set for its Code
and FAC
set for the Code
of the SiteType
associated with the Site
.
If Site
, CostCentre
or PermissionTree
entities matching these filter criteria were not found, the request will fail.
{
"messages": [
{
"code": "Core_ReferenceLookupNoMatchFound",
"message": "Reference lookup match could not be found",
"properties": [
"Warehouse->CostCentre_Id"
],
"severity": "error"
},
{
"code": "Core_ReferenceLookupNoMatchFound",
"message": "Reference lookup match could not be found",
"properties": [
"Warehouse->Site_Id"
],
"severity": "error"
}
]
}