Table of Contents

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:
  • AllOrNone - A batch request runs all resources provided in the batch within a single transaction (i.e. the whole batch of resources succeeds or fails together)
  • PerRecord - A batch request runs all resources provided in the batch within separate transactions (i.e. individual resources succeed or fail on their own)
?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:
  • NotStarted - not started yet
  • Running - currently running
  • Completed - completed
  • Cancelling - being cancelled by user
  • Cancelled - cancelled by user
  • Aborting - being aborted by system
  • Aborted - aborted by system
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.

«user»ScheduledBackgroundTask«system»JobScheduledJobBackgroundTaskBackgroundTaskStepexecuted byscheduled asscheduled assteps1..m

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:
  • Scheduled - scheduled for execution
  • Dispatched - dispatched for execution
  • Skipped - skipped execution
  • Faulted - could not be dispatched for execution
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 same preparedQueryBatchId.

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:

  1. Code - find the Id using the code specified for the converter
  2. 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"
        }
    ]
}