Book Contents

Book Index

K2 API - services K2

Book Contents

Book Index

Introduction

The K2 API is a Web application running on a Microsoft Internet Information Services (IIS) Web server. Through the application server K2, it makes the data of the K2 information system accessible and allows running scripts and reports.

Web services are based on the REST technique, ie. communication is under way via HTTP protocol and via standard methods GET (reading data), POST (create data), PUT (modification of existing data).

One can read the data or send the data either in XML or JSON format.

After entering the root URL address API into the browser can browse the basic description of the services and resources/operations using dynamic help.

pic_3917

Picture: Dynamic help of API

Note: If this page is displayed, it means, that the first communication API with the application server was successfully completed. If an error page IIS is displayed instead of it, then it means, that the communication was failed and probably the error is in API configuration or the application server does not run.

Book Contents

Book Index

Installation and basic settings

Book Contents

Book Index

Prerequisites

AS3USER='AN'
AS3PASSWORD='ANPassword'
AS3USERS=5
AS3IO=2000034152

Book Contents

Book Index

Recommended deployment for accessing API from the Internet

The K2 application server should always be installed on a server accessible only on the internal network. It is recommended to install the K2 API and any other web applications on a separate server, which is accessible from  the Internet and has limited access to the internal network allowing only communication with the  K2 AS.

Book Contents

Book Index

K2 API installation

This is done using the K2 Installer. The K2 API installation program checks the availability of the basic required components before starting the installation, eventually warns of missing components and the installation is stopped.

You need to enter some information during the installation:

Book Contents

Book Index

The most common problems with API installation and configuration

In most cases logging API or AS will help. SWS logging is activated in the web.config configuration file, using parameters LogPath (log file path), LogLevel (message types to be logged, at least Info is recommended for debugging), LogRequests (allows you to track the processing of individual SWS requests even multiple requests at once).

Book Contents

Book Index

Structure of URL address

Using the URL address we determine a means (mostly data, a record), we want to work or operation you run.

URL basic format:

<address of a server>/{xml/}<service name>/<means or operation>{?optional parameters}

Book Contents

Book Index

Web services

Data - A service which serves to work with data objects (data modules).

Meta – A service which enables to get a description of the data object structure.

Formation - It enables to run the scripts and reports.

FormationDefinition – It enables to get the definition of the scripts and reports.

Eshop – it groups special resources and operations for K2 e-shop.

Notification - Support for notifications.

Book Contents

Book Index

Data service

It serves to work with data (data objects) saved in K2.

Book Contents

Book Index

The list of the data object records

GET /Data/{classname}?<optional parameters>

The requirement serves to read a list of data objects of {classname} type. A list is paginated, all records are not read at once. Unless otherwise specified by using optional parameters, the first 30 records with values of default columns and all components of primary key are returned.

Parameters:

  1. {classname} – name of the data object class (e.g. TD_Part), or alias (an alternative name, e.g. Part)
  2. Fields – a list of the names of data fields the values of which should be returned, separated by comma. You can also enter a path to the fields through a link or enter the name of the child module followed by the name of a field from the child data object (individual field names of the path are separated by dot).
  3. orderBy - a list, of the names of data fields, according to which we want to sort the data, separated by comma. For a descending order it is necessary to take a sign - (minus) in front of the field name.
  4. pageSize – the required number of records on one page (how many records will be max. returned in one answer). When entering the value -1, the pagination will be banned and all records will be returned at once.
  5. page - a variable controls the shift to the other pages - possible values are last, prev, next, first
  6. pageState – internal variable which identifies the current page. A value of this variable (resp. the whole URL address) is always returned in an answer of the server.
  7. orOperator - it determines a logical conjunction between the individual conditions in conditions
  8. conditions – used for filtering data (ie compilation of selections of data module).

Note: One can use ProgName or AliasName (usually ProgName translated to English language) as a field name in all parameters. AliasName is always returned in an answer of API.

Structure of the answer:

<PagedList>
<Items> // List of data class name {classname}
</Items>
<FirstPageURL /> // URL address of the first page
<FirstPageURL /> // URL address of the next page
<FirstPageURL /> // URL address of the previous page
<FirstPageURL /> // URL address of the last page
RequestedFields /> // names of the returned data fields (e.g. default columns)
</PagedList>

Examples:

http://localhost/WS136/xml/Data/Part - it returns the first 30 partners with the default columns, ordered according to a primary key.

http://localhost/WS136/xml/Data/Part?fields=Name,ID_NO,Group.Abbr,EAddress.FullEAddress&orderBy=Name&pageSize=10 – it returns the first 10 partners listed by name with the following fields: name, ID-No, group abbreviation, to each partner all items e-mail addresses (field value FullEAddress).

http://localhost/WS136/xml/Data/Part?conditions=PartnerId;GT;10,Abbr1;LIKE*;Shell* - it returns max. the first 30 partners, whose partner´s number is greater than 10 and an abbreviation begins with "Shell".

POST /Data/GetList/{classname}

It is an alternative of the previous calling. In the body of the POST request is expected DataParameterFields object with the same parameters as possible to enter in the URL address GET request. This calling solves the limitations of the maximum length of the URL in the case of complex queries.

Structure of the request body:

<DataParameterFields xmlns="K2.Data">
<Conditions></Conditions>
<Fields></Fields>
<OrderBy></OrderBy>
<Page></Page>
<PageSize></PageSize>
<PageState></PageState>
<orOperator></orOperator>
</DataParameterFields>

Book Contents

Book Index

Detail of the specific data object

GET /Data/{classname}/{*PrimaryKeys}/?<optional parameters>

It serves to read a detail of the one concrete record specified by using a primary key.

Parameters:

Structure of the response:

<DataObjectWrapper>
<DOClassName /> // classname of a returned data object
<FieldValues> // collection with values of data fields
<NameValue> // one data field
<Name></Name> // name of data field (alias)
<Value> </Value> // data field value or referenced data object <NoPermission /> // flag that the user does not have the right to the field value
</NameValue>
...
</FieldValues>
<ItemURL /> // URL address of the detail of this data object
</DataObjectWrapper>

Note: NoPermission flag appears set to true only if the field value can not be obtained due to the evaluation of the rights to reading the field. In this case, no field value is sent - the Value property.

Example:

http://localhost/WS136/xml/Data/Part/15 - it returns a detail of a record of the partner number 15 with data fields by the default columns.

Book Contents

Book Index

Creating the new record

POST /Data/{classname}?<optional parameters>

Sending of the data object, which should be created and saved into the K2 database. Detail of the saved record is returned in the response.

Parameters:

Structure of the request body:

Structure of the response:

Book Contents

Book Index

Change of the existing record

PUT /Data/{classname}/{*PrimaryKeys}/?<optional parameters>

Sending the modified data object back to the K2 database. Detail of the saved record is returned in the response.

The process of modification of an existing record takes place so that we normally first read the data object through the API, edit the values of its fields and through this request we send it back to save it. It is important always to load and pass the value of the "TimeStamp" data field back (or more precisely of all system fields - more in the description of the detailed structure of data object of the Meta service). If the value of the TimeStamp field (or more precisely values of the system fields) will not be sent back, the operation fail. Purpose of the check of the TimeStamp field is to prevent collisions when the record is edited by more users at the same time (i.e. if the object was edited by another user between the events of loading and saving).

When editing dependant items, a particular item can be labeled "Deleted". After sending to API, this item will be deleted within saving changes in the header and items. An edited or deleted item must have stated all components of its primary key in the request.

Parameters:

Structure of the request body:

Example when deleting item:

<DataObjectWrapper xmlns="K2.Data" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<DOClassName>Part</DOClassName>
<FieldValues>

<NameValue>
<Name>ListBusinessChild</Name>
<Value i:type="ChildDataObjectWrapper">
<Items>
<Item>
<DOClassName>MBusiness</DOClassName>
<Deleted>true</Deleted>
<FieldValues>
<NameValue>
<Name>RID</Name>
<Value i:type="a:long" xmlns:a="http://www.w3.org/2001/XMLSchema">8495445311489</Value>
</NameValue>
</FieldValues>
</Item>
</Items>
</Value>
</NameValue>
</FieldValues>
</DataObjectWrapper>

Structure of the response:

Book Contents

Book Index

META service

It serves for getting a structure of the data objects

Book Contents

Book Index

The list of the available data objects published for the API

GET /Meta

Structure of the response:

<ArrayOfDataObjectMetaData>

<DataObjectMetaData> // information about one data object class
<Caption /> // displayed name
<ClassName /> // classname – class name used in URL
<IsHeader /> // flag, if it is a header type of an object
<V3ClassName /> // internal class name of the data object (class DM)
</DataObjectMetaData>
...
</ArrayOfDataObjectMetaData>

Book Contents

Book Index

The detailed structure of the specific data module

GET /Meta/{classname}

Structure of the response:

<DataObjectMetaData>
<Caption /> // displayed name
<ChildList /> // list of the itemized data object fields
<ClassName /> // classname – class name used in URL
<FieldList /> // list of scalar fields of the data object
<IsHeader /> // flag, if it is a header type of an object
<LinkList /> // list of data object binding fields
<PrimaryKeyFieldList /> // field list of primary key
<SystemFields /> //field list, which is necessary to transmit to change existing data object
<V3ClassName /> // internal class name of the data object (class DM)
</DataObjectMetaData>

Elements of lists ChildList, FieldList, LinkList, PrimaryKeyFieldList and SystemFields are objects FieldMetaData:

<FieldMetaData>
<Caption /> // Header field
<Description /> // Description field
<Name /> // Field name
<FieldName /> // Field name for URL and designation in data
<V3FieldName /> // The appropriate field name in K2 (ProgName)
<ValueType /> // Type of field values, it can be: Date, Time, DateTime, Bitmap, Numeric
<ValueType /> // Type of field values, it can be:
<IsReadOnly /> //The field is read only
<LinkClassName /> // Name (classname) of the binding field data object type
<LinkV3ClassName /> // Corresponding name of the data field of the binding field
<ChildClassName /> // Name (classname) of the item data object type
<Child V3 ClassName /> // Corresponding item data module name
<KeyIndex /> // Serial number of the field in the primary key
<ItemURL /> // Reference to the definition of the corresponding data object type, used for binding and item fields
</FieldMetaData>

Note: SystemFields collection is available from the K2.point version. It is necessary to load all fields stated in this collection and send them in a requirement to save the changes back when editing. API does not allow you to save the record without them.

Book Contents

Book Index

Formation service

It serves for getting a list of the available scripts and reports and for their running.

All scripts and reports used across API must be modified to run on an application server K2 and marked as AS3Compatible. They also have to be placed in the database (Scripts, reports module), they can not be in the file system. They can also be assigned to a specific data module, over which it makes sense to run them.

Book Contents

Book Index

The list of the available scripts and reports

GET /Formation?<optional parameters>

Parameters:

Structure of the response:

<ArrayOfFormationId>
<FormationId> // descriptive object of the script
<DefinitionURL /> // URL address for a detail of a script/report definition
<FormationID /> // Script / report file name
<ItemURL /> // URL for running the script / report
<Name /> // Script / report name
</FormationId>
...
</ArrayOfFormationId>

Book Contents

Book Index

Running script or report without specifying data

In this type of startup script does not pass AktDM on, script with him can not work. If the script is returned to standard output parameters (those whose values were changed at runtime script) or PDF file when you run the report.

GET /Formation/{folder}/{name}/{ext}?<script parameters>

Parameters:

Structure of the response:

<FormationOutput>
<URL /> // URL address of the output file
<Parameters> // values of output parameters
<Parameter>
<Name /> // Parameter name
<Value /> // Parametr value
</Parameter>
...
</Parameters>
<BulkData /> // output binary data
</FormationOutput>

Example:

http://localhost/WS136/xml/Formation/Standard/WkfWSProcDef/PAS?DefTypeAbbr=TEST – it runs the script ::\\DBNAME\Standard\WkfWSProcDef.PAS and sets the DefTypeAbbr parameter on "TEST" value to it.

Book Contents

Book Index

Running the script when specifying the data

Unlike the previous one it enables to send the definition of the data, for which the report or script should be run, before starting it and it also enables to send the parameter values. Other behavior remains the same.

POST /Formation/{folder}/{name}/{ext}

Structure of the request body:

<FormationInput>
<Conditions /> // conditions of the selection (format as in URL address)
<CurrentPrimaryKey> // values of primary key for the record
<Segment>
<Name /> // data field name
<Value /> // data field value
</Segment>
</CurrentPrimaryKey>
<DataObjectName /> // data object classname
<ORConditions /> // true - among the conditions is OR, false - AND
<Parameters> // script parameter values
<Parameter>
<Name /> // Parameter name
<Value /> // Parametr value
</Parameter>
</Parameters>
<PrimaryKeys> // list of primary keys of execution records
<PrimaryKey>
<Segment>
<Name />
<Value />
</Segment>
</PrimaryKey>
</PrimaryKeys>
<ReturnUrl /> // true - return the URL of the output file (eg PDF with report output)
</FormationInput>

Book Contents

Book Index

Running the script with HTML result

It enables to run the script, which generates HTML page, and display this page in a browser.

GET /Formation/html/{folder}/{name}/pas

A comprehensive example of this Web service call shows the standard script Example 127 - generate HTML for the Web services K2.

Book Contents

Book Index

Running the script or report and download output file

It allows to run the report or the script, that creates a file, and then download this file. Once the URL has been entered into the browser, the browser dialog to save/open the file will be displayed. In the case of a script, it is also possible to set the name of the downloaded file by using the SetOutFileName script procedure.

GET/POST /Formation/download/{folder}/{name}/{ext}

Eventual script parameters can be entered in the URL address (case of the GET method) or in the body of the POST request.

Example of a running script:

program TestDownload;
info
Title = 'TestDownload';
As3Compatible = true;
end;
modules
DM: TD_Job;
var
Exec: TAmExecutorNonVisual;
begin
DM.CreateDm;
DM.SetState(tfNormal, DM.PrimaryKey, False);
Exec := TAmExecutorNonVisual.Create;
try
Exec.AktDm := DM;
Exec.OpenCachedReport('TaskList.AM');
Exec.Execute;
Exec.ToExport('', 0, 9999, extyXLS, exdeToFile, prinPath + '\TasksList.xls');
SetOutFileName(prinPath + '\TasksList.xls');
finally
Exec.Free;
end;
end.

Book Contents

Book Index

Error handling when working with K2 API

Errors that occur during deserialization body demands before calling the Web Service code treats .NET and returns a status BadRequest without give out further details of the error. This error is returned in html format.

Error, which occurred in the API code, eventually on the application server, is returned as a text answer in the format: [ErrorKind]ErrorText.

ErrorKind – The list that specifies the type of error:

ErrorText - detailed description of the error.

Book Contents

Book Index

Example of calling of the special script

Example of the script

program ExampleWS(
ParamText {$DESC 'Vstupní textový parametr'}: string = '';
ParamCislo {$DESC 'Vstupní číselný parametr'}: integer = 0;
Output {$ DESC 'Output parameter'}: string = ''
);

info
Title = 'example WS´
AS3Compatible = true;
end;

modules
TD_Part;

begin
Output:= 'Values were passed: ParamText=' + ParamText + ', ParamNumber=' + IntToStr(ParamNumber) + ', Output=' + Output;

if (AktDM is TD_Part) then begin
Vystup := Vystup + ', AktDM=' + Trim(TD_Part(AktDM).Zkratka1);
end;

WriteLn(DateTimeToStr(Now) + ': ' + Output);

end.

Script has to be saved in the database (the Script and reports book) as ExampleWS.pas. AS3Compatible has to be set on true in the info section. By the setting this parameter, a script writer confirms, that he verified the translatability and executable of the script on AS (ie.he removed all the script visual parts and script can run in a multithreaded environment AS).

This script inserts a text with the input values of all script parameters into the output parameter Output, and if the script is run over the partners data module, it adds an abbreviation of the current partner. The current date and time and the same text write on a standard output of a script (in a directory of the current K2 user, a text file K2Export.txt with this text will be created).

Example of calling by using the GET request

Only the values of the parameters of the scripts are passed on, ActDm is not set in a script

URL:

http://localhost/WS136/xml/Formation/Special/PrikladWS/pas?ParamText=aaa&ParamCislo=123

The resulting answer:

<FormationOutput xmlns="K2.Data" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Parameters>
<Parameter>
<Description/>
<Name>Vystup</Name>
<Value i: type = "a: string" xmlns: a = "http://www.w3.org/2001/XMLSchema"> Values passed: ParamText=aaa, ParamCislo=123, Vystup=</Value>
</Parameter>
</Parameters>
</FormationOutput>

Example of calling by using the POST request

Settings ActDm on Partner with the number 5 and settings the parameters values.

URL:

http://localhost/WS136/xml/Formation/Special/PrikladWS/pas

HTTP header:

Content-Type: application/xml; charset=utf-8
Content-Length: 472

Body of a requirement:

<FormationInput xmlns="K2.Data" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:t="http://www.w3.org/2001/XMLSchema">
<CurrentPrimaryKey>
<Segment>
<Name>CisPart</Name>
<Value i:type="t:integer">5</Value>
</Segment>
</CurrentPrimaryKey>
<DataObjectName>TD_Part</DataObjectName>
<Parameters>
<Parameter>
<Name>ParamText</Name>
<Value i:type="t:string">Zadaný text</Value>
</Parameter>
<Parameter>
<Name>ParamCislo</Name>
<Value i:type="t:integer">12345</Value>
</Parameter>
</Parameters>
</FormationInput>

Note: "Content-Type" has to be stated in the header, ie what data we send to SWS, and further, in the body, there the data type has to be specified for a value for all Name-Value pairs, so that SWS knows, on which data type it should convert the text from XML document, when deserialization.

The resulting answer:

<FormationOutput xmlns="K2.Data" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Parameters>
<Parameter>
<Description/>
<Name>Vystup</Name>
<Value i: type = "a: string" xmlns: a = "http://www.w3.org/2001/XMLSchema"> Values passed: ParamText=Zadaný text, ParamCislo=12345, Vystup=, AktDM=DEMO TRADE</Value>
</Parameter>
</Parameters>
</FormationOutput>

Book Contents

Book Index

K2 API request authentication

The K2 API can operate in so-called anonymous mode only to debug service calls. In the production environment the authentication is always required. After installation API is standardly in this mode. Switching into anonymous mode is executed in the configuration file web.config in the installationdirectory of API by setting the parameter Anonymous = true.

For transmission and verification of the identity, it is necessary to set the standard HTTP Authorization header to {Username}:{HMACHash} in every request that is sent to API. {Username} is the user's username and {HMACHash } is a text string created by using HMAC MD5 algorithm. The key to hash is the user's password and the hashed message is the full URL address in the uncoded form (that is, without URL encoding of special characters) converted to uppercase. The resulting HMAC hash will be converted to the text by using base64 encoding.

You can alternatively pass on the hash directly in URL address by using "x-auth" parameter. In this case the whole URL of the request is built up, &x-auth= is attached to the end and the whole text shall beforwarded to the hash function. The result of the hash function is attached to the end of this text again.

Book Contents

Book Index

Examples

Example of algorithm in Java language

public static String calcHMAC(String src, String password)
{
SecretKeySpec sk = new SecretKeySpec(password.getBytes(), "HmacMD5");
Mac mac = Mac.getInstance("HmacMD5");
mac.init(sk);
byte[] result = mac.doFinal(URLDecoder.decode(src, "UTF8").toUpperCase().getBytes());
return Base64.encodeToString(result, Base64.NO_WRAP);
}

Example of algorithm in C# language

public static string CalcHMAC(string src, string password)
{
byte[] secretBytes = Encoding.UTF8.GetBytes(password);
HMACMD5 hmac = new HMACMD5(secretBytes);
byte[] dataBytes = Encoding.UTF8.GetBytes(Uri.UnescapeDataString(src).ToUpper());
byte[] computedHash = hmac.ComputeHash(dataBytes);
return Convert.ToBase64String(computedHash);
}

Example of algorithm in  Go language

func getAuthHeader(source_url string, username string, password string) string { // 1. initialize hmac encoder, key is password hmacEncoder := hmac.New(md5.New, []byte(password))

// 2. url decode & convert to uppercase urlDecoded, _ := url.QueryUnescape(source_url) upperFullURL := strings.ToUpper(urlDecoded)

// 3. hmac encode hmac encoder hmacEncoder.Write([]byte(upperFullURL)) hmacHash:= base64.StdEncoding.EncodeToString(hmacEncoder.Sum(nil))

return username + ":" + hmacHash

}

Example in K2 script

function CalcHMAC(ASrc, APassword: string): string;
begin
if not CreateHMacMD5HashBase64(AnsiUpperCase(HTTPDecode(ASrc)), APassword, Result) then
Result:= ' ';
end;

Example of algorithm in K2 script for entering hash directly in URL

function AppendAuthorizationHeader(aURL: string; aUsername: string; aPassword: string): string;
var
lHash: string;
begin
Result := aUrl;
if (Pos('?', aURL)=0) then
aURL := aURL + '?x-auth='
else
aURL := aURL + '&x-auth=';

if CreateHMacMD5HashBase64(AnsiUpperCase(aURL), aPassword, lHash) then

Result:= aURL + HTTPEncode(aUsername + ':' + lHash);

end;

Example of algorithm in PHP language

function getAuthorizationHeader($password, $fullUrl) {

  return base64_encode(hash_hmac('md5', mb_strtoupper(rawurldecode($fullUrl), 'UTF- 8'), $password, true));

}

Book Contents

Book Index

Advanced API configuration

All configuration of SWS is done using the common IIS configuration file - web.config. In addition to the specific K2 API settings (e.g. information about the application server, logging settings), additional settings of IIS and WCF services are included.

Book Contents

Book Index

Set the request size limit, or the maximum length of the URL address

In the case of sending large data using POST or PUT request to API, you may encounter the limit to the maximum request size that is applied by the default IIS settings. This limitation is manifested so that the API starts respond with error messages with the code 4xx, such as 400 Not found or 413 Entity too large. API from the version K2 move.02 contains the default settings of the maximum size of the received data to 50MB. This setting can be changed in the configuration file at the following locations:

  1. httpRuntime.maxRequestLength in the section system.web - general setting of maximum http request size. The value is reported in kB.
  2. requestLimits.maxAllowedContentLength in the section system.webServer/security/requestFiltering - setting of the IIS module "Request Filtering". With this parameter, it is possible to set the maximum size of the request body. Value is reported in bytes.
    Element <requestLimits> also has other attributes, e.g. maxQueryString or maxUrl, that can affect the maximum length of the parameters in the URL address, resp. the full URL address.
  3. binding.maxReceivedMessageSize - the size of the received message for a specific "binding" service. Value is reported in bytes.
    The <binding> element occurs multiple times in the configuration file (for HTTP and HTTPS communication), and it is usually necessary to set it in all places.
  4. Element <readerQuotas> for binding - can be used when sending overly complicated data (e.g. many nested XML/JSON levels, long text values of XML elements)

Book Contents

Book Index

"Binding" configuration

The standard configuration file lists the following bindings for all API modes: