Integration API
MindKey API is a REST API and it is hosted in Azure. Our API has predictable resource-oriented URLs, accepts JSON request bodies, returns JSON, and uses standard HTTP response codes, authentication and verbs.
API access prerequisites
- Local certificate and API key provided by MindKey
- List of IP numbers communicated by customers to our team
- Optional: GitHub account(s) shared by customers to our team for the upcoming API demo samples.
Customers will get access to the most common parts of the data model through our API. Therefore, the samples that we provide facilitate the data reading from our data model.
Contact your primary consultant to receive more information on the local certificate and the API key. For additional information about the certificate, see Certificate renewal process.
Tools suggestions
- Postman
- PowerShell
- Git
Authentication
The authentication process requires a certificate and an API key. MindKey generates a new certificate that can be used locally on the developer’s machine. Next, we provide an API key that adds an increased layer of security for customers. The API key uniquely identifies the database of the customers, and together with the certificate, they represent the authenticator.
Customers need to provide the list of IP numbers that will access the API.
We do not have customizable authentication for our API.
Integration samples and PowerShell module
You can request a Powershell or C# sample that illustrates how to use our API. The PowerShell samples use a so-called "shared" module developed internally by MindKey. The module can be supplied to customers and it helps to easily make requests to the MindKey API.
Quick start quide for your first request
The following PowerShell example describes how to obtain a list of employees in your MindKey.
Download the PowerShell modules from the integrations-shared repository to successfully complete the below steps.
In PowerShell, import the MindKeyRest module with:
Import-Module (PATH-TO- MindKey-Rest.psm1) -Force
Connect to the API using the Connect-MindKeyRest method provided by the module:
Connect-MindKeyRest “integration2.mindkey.com” -CertificateThumbprint THUMBPRINT -CustomerId CUSTOMERID
THUMBPRINT and CUSTOMERID are individual from one customer to another.
Next, you need to set up a request body by specifying which columns from the employee table you want to include. For more information on what columns are available and what else you can include in the post body, see the controllers section for how to get controller metadata.
$body = @{
columns = "EmployeeId, Name_FullName, ExternalReference, Address_Street, Address_ZipPostalCode, Address_City, Address_CountryRegion, SeniorityDate, PrivateMobilePhoneNumber_FullPhoneNumber, HomePhoneNumber_FullPhoneNumber, Email"
}
After this point, everything is in place to make your first request. To proceed, use the Invoke-MindKeyRestPost method, that is available in the ‘shared’ module.
$Employees = Invoke-MindKeyRestPost "employees/find" -InputObject $body
The employees variable now contains employee objects for every employee in your MindKey.
To try it out, you can write the names of all the employees as followed:
foreach($Employee in $Employees)
{
Employee.Name_FullName
}
For more examples in either Powershell or C#, check out the integration-samples repository.
CRUD operations
Create/Insert
controller_name/insert -InputObject $Object
$Object contains fields with values for the given controller.
All fields on a given target controller need a value. Fields defined on target controller that are not assigned a value
are updated with value equal $null.
The code below is an example of the INSERT command for a controller.
// FILE with definition of target controllers:
namespace NameSpaceTarget
{
public class ControllerInsertTarget
{
public string ControllerId { get; set; }
public string ControllerField1 { get; set; }
}
}
$Controller = New-Object NameSpaceTarget.ControllerInsertTarget
$Controller.ControllerId = "ControllerId"
$Controller.ControllerField1 = "Controller Field1 value"
try
{
$insertedController = Invoke-MindKeyRestPost "controllers/insert" -InputObject $Controller
}
catch
{
Add-Error "An critical error occurred while inserting controller: $($_.Exception)"
}
The $insertedController returns a full controller record with all fields from controller in MindKey.
Update
controller_name/update?Key=$KeyValue -InputObject $Object
$Object contains fields with values for the given controller. All fields on a given target controller need a value.
Fields defined on target controller that are not assigned a value are updated with value equal $null.
The code snippet below shows an example for the UPDATE command for a controller.
// FILE with definition of target controllers:
namespace NameSpaceTarget
{
public class ControllerUpdateTarget
{
public string ControllerField1 { get; set; }
}
}
$Controller = New-Object NameSpaceTarget.ControllerUpdateTarget
$Controller.ControllerField1 = "Controller Field1 value update"
try
{
Invoke-MindKeyRestPost "controllers/update?ControllerId="+$controllerIdValue -InputObject $Controller
}
catch
{
Add-Error "An critical error occurred while updating controller: $($_.Exception)"
}
Delete
{{controller_name}}/delete?Key=$KeyValue
The DELETE command for a controller looks like demonstrated below:
try
{
Invoke-MindKeyRestPost "controllers/delete?ControllerId="+$controllerIdValue
}
catch
{
Add-Error "An critical error occurred while deleting controller: $($_.Exception)"
}
Write
{{controller_name}}/write?Key=$KeyValue -InputObject $Object
$Object contains fields with values for given controller. All fields on a given target controller need a value. Fields
defined on target controller that are not assigned a value are updated with value equal $null.
The WRITE command either inserts or updates the given controller, depending if the key value exists or not.
The example below shows how the WRITE command for a controller looks like.
// FILE with definition of target controllers:
namespace NameSpaceTarget
{
public class ControllerWriteTarget
{
public string ControllerId { get; set; }
public string ControllerField1 { get; set; }
}
}
$Controller = New-Object NameSpaceTarget.ControllerWriteTarget
$Controller.ControllerId = "ControllerId"
$Controller.ControllerField1 = "Controller Field1 value"
try
{
Invoke-MindKeyRestPost "controllers/write?ControllerId="+$$Controller.ControllerId -InputObject $Controller
}
catch
{
Add-Error "An critical error occurred while writing controller: $($_.Exception)"
}
Find/Select/Read
try {
$ControllerId = 'controllerId'
Add-Info ("Find Controller: " + $ControllerId)
# Setup search condition
$body = @{
searchCondition = @(
@{
column = "ControllerId"
value = $ControllerId
}
)
}
$Result = Invoke-MindKeyRestPost "controllers/find" -InputObject $body
if (!$Result) {
Add-Info ("No Match for criteria: ControllerId = " + $ControllerId)
}
}
catch {
Add-Error "An critical error occurred while getting controller: $($_.Exception)"
}
Logic operators AND/OR and TransDate
Logical operators are used to change the default conditon AND to OR. If a logical operator is not given, the search
condition is by default AND.
Logical operators can either contain AND or OR. They cannot be used both in the same search condition.
Below you can find an example including logical operators:
$body = @{
columns = "ControllerId, Controller_Name"
searchCondition = @(
@{
column = "ControllerId"
value = $ControllerId1
},
@{
column = "ControllerId"
value = $ControllerId2
logicalOperator = "OR"
}
)
}
$Controllers = Invoke-MindKeyRestPost "controllers/find" -InputObject $body
Condition Operators
Condition operators are used to change the default condition EQUAL. If a conditional operator is not given, the search
condition is by default EQUAL.
Conditional operators can have the values NOTEQUAL, LESS, GREATER, LESSOREQUAL, GREATEROREQUAL or LIKE.
$body = @{
columns = "ControllerId, Controller_Name"
searchCondition = @(
@{
column = "ControllerId"
value = "100"
conditionOperator = "NOTEQUAL"
}
)
}
$Controllers = Invoke-MindKeyRestPost "controllers/find" -InputObject $body
Employee Position Mode
You can add a position mode to pull connected positionVersions records of different types.
Without given a postionMode many positionVersion fields are available directly from the employee controller. The
default join mode for this is CurrentOuterjoin.
From the employee controller the fields can be picked by using their short names like OrganizationId, LocationId,
etc.
Fields from postionVersion on the employee controller are fields for the actual date. If no positionVersion is
present for employee on the actual date, these fields remain empty.
To pick the correct positionVersion controller, positionMode can be added to the employee search.
There are four different modes that you can add:
- positionMode = "CurrentOuterJoin". This mode returns all employees. If a
positionVersion recordis found, the fields frompositionVersionare also returned. - positionMode = "CurrentInnerJoin". This mode returns employees, where a
positionVersionrecord exists. - positionMode = "TerminatedInnerJoin". This mode returns terminated employees since a given date.
TransDateis a mandatorycustomSearchConditionfor this operation. - positionMode = "FutureInnerJoin". This mode returns employees with a future employment from a given date.
TransDateis a mandatorycustomSearchConditionfor this operation.
The positionColumns command needs to be assigned together with the positionMode. At the same time, you can enter
here the fields to be picked from the positionVersion controller.
The customSearchCondition command needs to be used for TerminatedInnerJoin and FutureInnerJoin. Proceed by
entering the date when the transctions should be selected. The syntax is as follows:
# Terminated or Future Employments since this date
"customSearchCondition" = @(
@{
condition = "TransDate"
value = "2019-07-01T00:00:00"
onlyParameter = $true
}
)
Fields returned from the positionVersion on the employee controller are for instance
named $Employee.PositionVersion_Organizationid.
User defined fields
To retrieve attached columns for user defined fields on the employee record,
add userDefinedColumns = "UserDefinedColumnName" to the employee search.
The userdefined fields returned on the employee controller receive for instance names
like $Employee.UserDefinedColumn_UserDefinedColumnName.
Fields used in the API should not be renamed in MindKey. Renaming the fields causes the script to fail as the field name and selection will be wrong.
Integration Leave, Time Tracking, and Mileage
You can integrate leave and/or time-tracking by using the LeaveIntegration, timeTrackingIntegration,
and mileageIntegration records. These records are created when leave, time-tracking, and mileage are approved in
MindKey.
The records have status fields specific for an API integration. The status can have the following value:
1= ready (ready to "export" transaction)2= found (export job has read the transaction)3= updated (export has finished updating the transaction)
In this case, note the below observations:
- When the API is running it should read all transactions with status
1or status2. - When starting the update job, all transactions with status equal to 1 should be updated to status =
2. - When export job is finished, all handled transactions should be update to
3.
Logging results to MindKey
Any integration can write to the System log that MindKey provides. MindKey users can use it to identify and be notified of eventual errors.
The endpoint for the log is POST syslogs/insert and the Powershell sample below is of an object
that can be posted to the syslog. All the values in {{}} are to be replaced and the functions GetErrorCount
and Get-WarningCount are from our Powershell module.
The code also illustrates 3 possible statuses where 1 means success, 2 means warning, and 3 means error.
We recommend the users of MindKey to set up notifications based on these statuses.
$SysLog.MessageText = {{Log_As_String}}
$SysLog.TransDateTime = {{Current_DateTIme}}
$SysLog.HostName = {{Machine_Name / Ip_Address}}
$SysLog.UserName = {{User_Running_Integration}}
$SysLog.JobName = {{Integration_Name}}
$SysLog.Application = 'MindKey Integration Service'
if (Get-ErrorCount -ge 1)
{
$SysLog.Status = 3
}
else
{
if (Get-WarningCount -ge 1)
{
$SysLog.Status = 2
}
else
{
$SysLog.Status = 1
}
}
Controllers
You can also obtain the entire list of controllers from the API. For that, call the following endpoint with a GET request in Postman or in the chosen tool:
{{api_root}}/{{customer_id}}/system/controllers
{{api_root}} = integration2.mindkey.com/api
More information about an individual controller can be obtained by calling:
{{api_root}}/{{customer_id}}/{{controller_name}}/metadata
This returns the data model for the selected controller and the available request methods, filters, and possible fields in a JSON post body.
Metadata samples for controllers and get information
Request
{{api_root}}/{{customer_id}}/leaveIntegrations/metadata
Response
{
"entityInformation": ["Table: LeaveIntegration"],
"filterUpdateDelete": ["LeaveId", "EmployeeId", "StartDate", "EndDate", "PayrollUpdateStatus", "RowNumber"],
"body": [
"columns",
"integrationSystemName",
"searchCondition",
"top",
{
"customSearchCondition": ["FromDate"]
}
]
}
In the above code snippet:
- The
entityInformationsection explains which tables and views from MindKey are used for this controller. - The
filterUpdateDeletesection describes the fields that can be used for filtering when updating or deleting records in MindKey. - The
bodysection always has the subsectionscolumns,top,SearchConditionandintegrationSystemName.- In the
columnssubsection, you can specify either all columns from controller using "*" or specific columns. - In the
topsubsection, a number can be specified to only return this exact number of records. - In the
searchConditionsubsection, you can specify different selection criteria. By default, criteria areAND. - In the
integrationSystemNamesubsection, you can establish the names that are created in theintegrationsystemsetup in MindKey. The export value is returned if values for the givenintegrationsystemare set up in the integration exportkeys.
- In the
- In the
CustomSearchConditionsection,FromDatecan be given and then only records created or modified after this date are returned.
IntegrationSystemName
If integrationsystem "Visma" is created in Integrationsystems and a value for integrationssystem "Visma" and
Table LeaveCode is created, a column with name LeaveCodeName_ExportKey is returned for all controllers where
field LeaveCodeName exists.
If no value is setup for the actual leave code in the integration exportkeys, the column returns null.
Below you can find a PowerShell LeaveIntegration export example:
$body = @{
columns = "*"
integrationSystemName = "MyLeaveSystem"
searchCondition = @(
@{
column = "PayrollUpdateStatus"
value = "2" # 1 = ReadyForPayroll, 2 = MovedToPayroll, 3 = PayrollUpdated
}
)
}
This example returns the following columns:
{
"LeaveId": "1110",
"Version": 1,
"LeaveCodeName": "Vacation",
"StartDate": "2019-09-10T00:00:00",
"EndDate": "2019-09-13T00:00:00",
"BalanceEffect": "-4.0",
"BalanceUnit": 1,
"EmployeeId": "1086",
"Origin": 0,
"PayrollUpdateStatus": 3,
"PayrollDateTime": "2020-04-01T11:14:04",
"Correction": false,
"RowNumber": 1530,
"CreatedBy": "mindkey@mindkey.com",
"CreatedDateTime": "2019-11-21T16:19:53",
"ModifiedBy": "MindKey Service",
"ModifiedDateTime": "2020-04-01T11:14:04",
"VersionStamp": 4,
"DocumentsExists": false,
"ExternalStatus": 0,
"EmployeeId_ExportKey": null
}
Last column EmployeeId_ExportKey is returned because EmployeeId column is selected and a LeaveCode has been setup
for integrationsystem equal to MySalarySystem.
Since no setup value or EmployeeId equal to "MFU" exists, null is returned.
If you setup LeaveCode for integrationsystem to be equal to MySalarySystem, the LeaveCodeName_ExportKey column
is returned.
HTTP headers for MindKey REST requests
In the quick start guide above, we used the MindKeyRest Powershell module, which also handled the needed request headers. If you do not use that, you need to specify them by yourself.
The table below presents the standard request headers that MindKey accepts, as well as the custom MindKey headers that you can use.
| HTTP Header | Required | Description |
|---|---|---|
| Accept (standard) | Optional | Accept indicates the formats the client accepts for the response. This header pairs with the Content-Type header, which specifies the format required by MindKey for the request. Currently, all MindKey REST interfaces require request bodies to be formatted in JSON, and JSON is the default and only format returned in response bodies. For more information, see Microsoft Time Zone Index Values. Example: Accept: application/json |
| Content-Type (standard) | Conditionally required
| Content-Type indicates the format of the request body provided by the client. This header is required for all POST and PUT operations; application/json is currently the only supported value. Example: Content-Type: application/json |
| TimeZone (MK custom) | Conditionally required
| TimeZone must be specified in request header if the body for a post operations containing a DateTime value that is passed as UTC. Example: TimeZone: Romance Standard Time. For a full list of accepted values, see Microsoft Time Zone Index Values. |
| SystemUser (MK custom) | Optional | SystemUser specifies a username, that is used when logging who modified data in MindKey. It defaults to ‘MindKey Service’ if not set. |
| ApplicationName (MK custom) | Optional | |
| Culture (MK custom) | Optional | |
| Language (MK custom) | Optional | Language defines in which language the user wants to receive the response. Default to en-US, if not set, or set to unsupported language. |
Errors
The MindKey integration API uses standard HTTP status codes. 2xx codes indicate success, 4xx codes indicate an error in the information provided, and a code in the 5xx range indicates an error on MindKey's servers. The table below describes the common status codes.
| Error code | Description |
|---|---|
| 200 | The request worked as expected. |
| 404 | The resource could not be found. |
| 405 | Method not allowed. Encountered when using a HTTP method that is not allowed on this endpoint. |
| 500 | Something went wrong in the MindKey API. |