REST Services Version 1 2022.2

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 90

Kinetic REST Services

Guide v.1

Version 2022.2
Disclaimer
This document is for informational purposes only and is subject to change without notice. This
document and its contents, including the viewpoints, dates and functional content expressed herein
are believed to be accurate as of its date of publication. However, Epicor Software Corporation makes
no guarantee, representations or warranties with regard to the enclosed information and specifically
disclaims any applicable implied warranties, such as fitness for a particular purpose, merchantability,
satisfactory quality or reasonable skill and care. As each user of Epicor software is likely to be unique
in their requirements in the use of such software and their business processes, users of this document
are always advised to discuss the content of this document with their Epicor account manager. All
information contained herein is subject to change without notice and changes to this document since
printing and other important information about the software product are made or published in
release notes, and you are urged to obtain the current release notes for the software product. We
welcome user comments and reserve the right to revise this publication and/or make improvements
or changes to the products or programs described in this publication at any time, without notice.

The usage of any Epicor software shall be pursuant to an Epicor end user license agreement and the
performance of any consulting services by Epicor personnel shall be pursuant to Epicor's standard
services terms and conditions. Usage of the solution(s) described in this document with other Epicor
software or third party products may require the purchase of licenses for such other products. Where
any software is expressed to be compliant with local laws or requirements in this document, such
compliance is not a warranty and is based solely on Epicor's current understanding of such laws and
requirements. All laws and requirements are subject to varying interpretations as well as to change
and accordingly Epicor cannot guarantee that the software will be compliant and up to date with such
changes. All statements of platform and product compatibility in this document shall be considered
individually in relation to the products referred to in the relevant statement, i.e., where any Epicor
software is stated to be compatible with one product and also stated to be compatible with another
product, it should not be interpreted that such Epicor software is compatible with both of the
products running at the same time on the same platform or environment. Additionally platform or
product compatibility may require the application of Epicor or third-party updates, patches and/or
service packs and Epicor has no responsibility for compatibility issues which may be caused by
updates, patches and/or service packs released by third parties after the date of publication of this
document.

Epicor® is a registered trademark and/or trademark of Epicor Software Corporation in the United
States, certain other countries and/or the EU. All other trademarks mentioned are the property of
their respective owners.

Copyright © 2022 Epicor Software Corporation Epicor.

All rights reserved. No part of this publication may be reproduced in any form without the prior
written consent of Epicor Software Corporation.
Kinetic REST Services Guide v.1

Table of Contents

Getting Started 6
Introduction 6
Kinetic REST API Overview 6
How You Can Use OData REST Services 6
HTTP Methods Used in Kinetic 7
Configuring REST 7
Kinetic REST API Setup 8
Accessing the REST Root Directory 8
Setting a Row Limit 9
Tracing REST Calls 9
Using REST API Interactive Help 9
Acessing Kinetic UX REST API Interactive Help 10
Tour of the Kinetic UX REST Help 10
Service Controls and REST Headers 14
OData List 17
RPC (Custom Methods) 18
Business Activity Queries Help 20
Calling Kinetic Services 22
OData Datasources 23
Methods 24
Using OData Querying 27
OData Querying 27
Querying for Entity Set vs Single Entity 27
Navigating Relationships 28
Using OData Parameters 29
$select 29
$filter 29
$top 32
$skip 33
$orderby 33
$expand 33
$inlinecount (API v.1) 34
Displaying Data in OData Applications 35
Linking to Browser 36
Displaying Service and BAQ Data in Excel® 36
Displaying OData Feed as a PivotTable or a PivotChart 40
Working with Kinetic REST API 41

3 January, 2023
Kinetic REST Services Guide v.1

Using Postman 41
Setting Up Postman 41
Executing a GET 42
Executing a POST 42
Diagnosing an Error 43
Creating a New Customer 43
Updating a Customer 44
Deleting a Customer 44
Updating a Child Entity 45
Deleting child User Code; Leaving User Type intact 45
Executing a BAQ 46
Working with Updatable BAQs (UBAQs) 46
Creating a New Record 46
Updating a Record 47
Deleting a Record 47
Working with Custom Methods 48
Example 1 - HTTP POST 49
Example 2 - HTTP POST 49
Example 3 - HTTP GET 50
Example 4 - HTTP GET 50
Using Custom Headers 51
API Key Header 51
CallSettings Header 52
SessionInfo Header 52
OnBehalfOfToken Header 53
License Header 54
Trace Flags and Caller Trace Headers 55
ContextHeader Header 56
Creating Web Applications Using REST Services 57
Setting up the environment 57
Running the sample application 57
Reviewing the application code 58
Creating and testing the Search REST call in Postman 59
Generating Code in Postman 61
Adding the Postman sample code to the web application 61
Display the Search Results on the Web Page 63
Wiring the Search Query to the REST Query 64
Congratulations! 65
Calling REST with Azure AD token in C# 65
Creating a Visual Studio Project 65

4 January, 2023
Kinetic REST Services Guide v.1

Adding NuGet Package 66


Adding AzureADAuth Class 66
Adding Token Header to the Server Request 71
Writing Code to Call REST API 72
Calling REST with Azure AD token in JavaScript 72
Calling BPM Auto Print, MRP, or Multi-Company Processes 76
Troubleshooting and Security 77
Understanding REST API Exceptions 77
Mapping Between Kinetic Service Exceptions and HTTP Error Codes 77
Handling Errors 81
Setting Up Data Security 82
Basic Authentication 83
Token Authentication 83
Single Sign-On 85
Azure Active Directory Token Authentication 86
CORS Support 89

5 January, 2023
Kinetic REST Services Guide v.1

Getting Started
Introduction

Kinetic REST API Overview


Through the REST Application Program Interface (API), services link applications more easily through
internet-type connections. The Representational State Transfer (REST) architecture considers both data
and functions as web resources, and these items are accessible through unique Uniform Resource
Identifiers (URIs), or endpoints. A REST server grants access to these web resources, and then REST
clients access these resources to display them.

These services use the OData REST Protocol. This protocol adds query capabilities and metadata
descriptions that enable OData-aware applications to display real-time Kinetic data. Applications can
then communicate with Kinetic through REST services in the same way a web browser interacts with a
website.

How You Can Use OData REST Services


You can use the OData REST services to connect Microsoft® Excel®, Microsoft® PowerBI®, or other
applications that understand OData. For example, link a Kinetic Business Activity Query (BAQ) REST
Service with Microsoft Excel; Excel then displays real-time views of your Kinetic data. You can also

6 January, 2023
Kinetic REST Services Guide v.1

leverage Excel features, such as PivotTable Report or PivotChart, to further review and evaluate your
live data. You can also build custom applications. For example, you could write a new iOS application
using Objective-C or web application with JavaScript. You could then integrate it with a Kinetic REST
Service, such as PO Entry, to view and edit purchase orders.

HTTP Methods Used in Kinetic


RESTful web services expose a set of resources as URIs, and so various platforms can access this web
service to exchange data. Because the resources are identified as URIs, they provide a global address
space for both the resources that contain data and the services which consume them. In Kinetic, these
resources are updated through a fixed set of HTTP methods:

l GET – Retrieves the current state of a resource from the database.


l POST – Creates a new resource. You can also use the POST method to invoke methods that
update records in the database.
l PATCH – Similar to POST, updates changed resource in the database as well. However, this
method only updates data elements that have changed; it does not update the entire object.
l DELETE – Removes a resource from the database.
The POST and GET methods are frequently used to invoke methods remotely. If the method will change
the state of an object (like saving a record in a database), you use the POST method. When the method
does not change the state of an object (like returning a count of open orders), you use the GET method.

In Kinetic, the REST API uses the PATCH method to update data objects while the POST method is used
for invoking service methods. By using the PATCH method, the API ensures the data objects update as
expected. Then by using the POST method, the API ensures that the service methods invoke
successfully.

Since the resources are available as global URIs, you can access them through a variety of third-party
applications and programming languages.

Code connections with the URI resources run as self-contained, stateless interactions. The code locates
the URI resource within the RESTful web service, pulling the data the resource contains into the
receiving application. The security of these transactions is ensured by using HTTPS protocol and
applying any existing data security defined for the Kinetic user.

Configuring REST
In this section, learn how you configure REST on your Kinetic application server.

7 January, 2023
Kinetic REST Services Guide v.1

Kinetic REST API Setup


REST API is enabled in Kinetic by default. However, if you have problems with running REST requests
from the examples in this guide, check if the REST API-related settings have been activated in the
<runtime> section of the application server web.config file. You can easily locate them by searching for
Uncomment this part to enable RESTApi string.

HTTPS protocol is required for all REST requests against the Kinetic REST API. You must
configure HTTPS binding in your application server settings.

In very special cases – for example, when SSL Offloading is activated, it is possible to allow REST
requests via a non-encrypted HTTP channel. To enable insecure calls, add the following setting to the
appSettings section of your server web.config file:

<add key="AllowInsecureRestApi" value="True" />

In this case, all requests will contain payloads in plain text including authentication data.
Insecure requests against Kinetic REST API must never be used in production
environments.

Accessing the REST Root Directory


Kinetic REST Services are grouped together under a top level, or parent Uniform Resource Locator
(URL). This URL is the REST Service Root URL, and it is located on your server installation..

Before you can use a REST service, you first locate its unique URL value. You can get the complete list of
all ERP/ICE services available in the system by calling the REST Service Root Directory. You can also
learn which methods and parameters you can use with the service.

The directory path uses the following format:

V1:

https://[KineticServer]/[KineticInstance]/api/v1/

For example, the URL for the Customers resource of the Customer service that includes a root service
path would be:

https://KineticServer/Kinetic/api/v1/Erp.BO.CustomerSvc/Customers

You may be prompted for credentials when accessing API via browser. Enter standard Kinetic Username
and Password.

8 January, 2023
Kinetic REST Services Guide v.1

Setting a Row Limit


By default, the number of returned rows in data retrieval is limited to one hundred.

To specify a different number, add the following setting into the appSettings section of your server's
web.config file:

<add key="DefaultMaxRowCount" value="<your number or 0 to remove the limit>" />

Tracing REST Calls


You activate server log tracing for REST calls within the AppServer.config file. Your server logs will then
contain call entries for the REST services that interact with your database.

To activate REST traces in a server log:

1. Go to your server machine.


2. Navigate to the Server folder for Kinetic. For example, C:\Epicor\Kinetic\Kinetic_2021.2\Server.
3. Open the AppServer.config file.
4. Activate the server tracing by adding the following flag:

<add uri="trace://ice/fw/restapi" />

The server log will then contain information about REST call processing.

6. You can also add the following trace:

<add uri="trace://ice/fw/servicecaller" />

This shows what service was loaded when a call started its run.

Using REST API Interactive Help


Kinetic provides a native interactive API help system. This is the primary build-in tool for basic testing of
Kinetic REST API. Before you set up your external application to consume Kinetic data, use this resource
to explore the available web services, service models, required input parameters and fields, try out API
calls.

Use the external testing tools like Postman or cURL for more complex API testing
involving POST requests against Custom Methods.

REST API Interactive Help is available in two formats providing similar user experience in different UIs:

9 January, 2023
Kinetic REST Services Guide v.1

l Kinetic UX REST API Interactive Help - delivered as an interactive Kinetic API help application
supporting both REST APIs - v.1 and v.2.

l Classic UX REST API Interactive Help - previous version of API Interactive help (v.1 and v.2).

The legacy help page found at https://[KineticServer]/[KineticInstance]/api/help/


automatically redirects to the new Kinetic UX Help page. If necessary, you can point this
URL to, for example, the legacy Swagger v.2 help version by adding the below line to the
AppSettings section of the server web.config file:

<add key="RESTHelpPage" value="SwaggerUI2" />

Acessing Kinetic UX REST API Interactive Help


The Kinetic Help application is found in the Application Server directory under the apps/resthelp/
subfolder. Use the following URL format to get access to the Kinetic UX REST API Interactive Help:

https://[KineticServer]/[KineticInstance]/apps/resthelp/

When prompted, enter your Kinetic user credentials for authentication.

The Key features of the Kinetic UX REST Help page include:

l Support for all types of authentication:


o Basic Authentication - user name and password.
o Windows SSO Authentication - Domain\Username and Windows password.
o Azure Active Directory - requires adding https://[KineticServer]/
[KineticInstance]/apps/resthelp/ redirect URI in the Azure AD Server application.
o Epicor Identity Provider - requires registering https://[KineticServer]/
[KineticInstance]/apps/resthelp/ and https://[KineticServer]/
[KineticInstance]/apps/resthelp/silent-renew.html redirect URIs in the IdP JavaScript
application.
l Ability to select a company to be used as a current company parameter in all REST calls.
l Ability to add services to Favorites, building Favorites groups.
l Ability to preset REST call headers, such as API Key, Call Settings, or Authorization.

Tour of the Kinetic UX REST Help


Kinetic REST Help Home Page provides a workspace to access help controls from a single location.

The following is the list of controls found on the Menu Bar:

10 January, 2023
Kinetic REST Services Guide v.1

1. Use the Home icon to access the REST Help Home Page.
The Browse menu displays the contents of the Kinetic REST API Help.

a. Use the Search box to locate the service you need - for example, Customer.
b. Review the Service List - make a selection to display the list of all available services
pertaining to:

l BO (Business Objects) Namespace


l Lib (Library) Namespace

11 January, 2023
Kinetic REST Services Guide v.1

l Proc (Processes) Namespace


l Rpt (Reports) Namespace
These mirror the existing services deployed to the Kinetic application server. If you have
had a custom-made service for your deployment, it appears here too.

OData protocol is not supported for Lib, Proc, and Rpt service types. When you select a
service of this type, use the Remote Procedure Call (RPC) tab to explore the list of
available Custom methods.

c. Business Activity Queries - Select this item to browse Business Activity Queries (BAQs) via
REST API v.2.
d. Epicor Functions - From this section, you can access testing tools for all the Functions
enabled and published in the system across all available companies. Functions are
exposed in the REST API v.2 only.
2. You can mark your favorite services and check out recently viewed items here.

Here's how you add Favorites groups:

l Launch the Browse menu.


l Select a service and click the star icon next to its name. Note you can also mark Business
Activity Queries and Epicor Functions as your favorites.
l You can keep the default service Name or change it to something that makes better sense
to you. This is how the service will display in the Favorites group.
l By default, your items will be kept in the group named Favorites. You can use the Plus (+)
sign to create a new group. This way, you can better organize your frequently used
services.

l Save your changes.

12 January, 2023
Kinetic REST Services Guide v.1

l Your Favorites are now accessible from the REST Help Home Page. You can modify the
Favorites list structure and its contents by clicking the Edit icon next to a group.

3. Use the User menu to set a company for performing REST calls.

l The Company drop-down displays the list of companies you have access to.

l The selected company is used as the current company parameter when performing API
REST v2 calls.

13 January, 2023
Kinetic REST Services Guide v.1

Company selection only applies to Kinetic UX REST Help application; it


does not affect any other recently opened Kinetic sessions.

Service Controls and REST Headers


This section guides you through the available service controls. It also explains how to configure values
sent in the header when a REST call is made.

1. Use the Search box to locate the service - for example, Erp.BO.CustomerSvc:

14 January, 2023
Kinetic REST Services Guide v.1

2. The left-hand menu displays the list of methods retrieved from swagger documents. Notice you
can switch between two tabs:

l OData - displays OData methods for the service.


l RPC - displays Remote Procedure Calls (custom methods) available for the service.
You can search for the service you need. Once you made the selection, the Services pane lists all the
methods of the selected service.

3. In the API Version drop-down list, you can switch between working with REST API Services v.1 or
v.2.
4. On the right side of the screen, use the Open Swagger document link to display the full swagger
document for the service in a separate window.
5. If needed, you can navigate to the previous version of the REST API Help v2 by clicking the Go to
old help page link. By default, it takes you to the REST API v.2 Help Home Page. Both Open
Swagger document and Go to old help page links open in a separate window and use browser's
basic authentication.
6. Kinetic Help page allows setting up REST Headers. By default, the API Key header is displayed,
however, you can add additional headers as needed.

7. You can add additional headers for your REST calls.

l For example, in the drop-down list, select Call Settings and press Add Header.
l In the Call Settings pane, for Plant/Site parameter, enter Mfgsys.

15 January, 2023
Kinetic REST Services Guide v.1

l Set the new header.

l You can add only one header of each available type. Creation of custom headers is
not supported.
l Call Headers are set for the duration of your user session. They are removed if you
exit or reload the UI.
l When you execute the call, specified headers are presented in the cURL response.

Review the list of supported headers:

Header Description

Call Settings Allows specifying various parameters such as Company or Site for the
duration of the call.

Session Info Allows sending GUID of the session you are logged in.

License Allows specifying GUID for the Claimed License and Session where
you are logged in.

Call Info Allows specifying Correlation ID GUID for the call.

16 January, 2023
Kinetic REST Services Guide v.1

Header Description

Authorization Allows customizing call authentication. Note that by default, current


token is used for authentication. You can use this header to test
additional settings:

l Do not send header - no Authorization header is sent with the


call.
l Use Basic Authentication - specify user name and password.
l Set header value - set Authorization header value manually, by
for example, specifying a token value, such as "Bearer x.y.z".

OData List
OData as a standard provides different capabilities - for example, describing the service structure and
contents.

1. Search for and select the Customer service (Erp.BO.CustomerSvc).


2. Select the API Version (by default it is set to v1)
3. On the OData List, select $metadata; then click:

V1: GET /$metadata

4. Press Try it out.

5. Press Execute. Note the Response Body displays the full service metadata including:

l Entity Sets (Tables);


l Function Imports (Methods);
l Association Sets (Table Relationships);
l Entity Types/Keys/Properties (Tables/Keys/Fields).
6. Press the Clear button. The response section collapses.
7. In OData list, select the Customers method. The available HTTP methods display.
8. Depending on the API version you selected, click:

V1: GET /Customers

In the Responses section, the Example Value view is displayed by default.

17 January, 2023
Kinetic REST Services Guide v.1

9. Select Model and expand the definition. In the response, note JSON description of the fields
useful for tools and displaying headers in programs.

10. Scroll up and press Try it out.

11. Press Execute. Note the response sections:

l Curl - A command that can be used in cURL, a command line tool to execute URLs;
l Request URL - The URL you can type in your browser to get back information;
l Response Code - Standard web response codes.

Example: Code 200 = Success, 404 = Page not found, etc.

l Response Body - The data response from the URL;


l Response Headers - Any Business Process Management (BPM) form information would be
returned in the Context Header response.

RPC (Custom Methods)


Custom methods do not support OData. These are all the ad hoc custom methods exposed by the
service. Custom methods can be used with the GET and POST verb in code.

By default, HTTP GET is enabled in both REST APIs - v.1 and v.2 - for methods that do not modify data,
such as GetByID, GetList, or GetRows. While HTTP POST methods are still fully supported for these
custom methods, they are marked as obsolete. Epicor recommends any new testing and development
is performed using HTTP GET.

1. Search for and select the Customer service (Erp.BO.CustomerSvc).


2. Select the RPC (Remote Procedure Call) tab to display custom methods.
3. First, test one of the methods supporting HTTP POST calls only. In HTTP POST calls, the
parameters are specified in the request body in JSON.

l Search for and select the GetByCustID method.


l Depending on the API version you selected, click and expand:

V1: POST /GetByCustID

l Click Try it out.

l Change the values in the input body to:

18 January, 2023
Kinetic REST Services Guide v.1

{
    "custID": "addison",
    "withShipTo": true
}

Addison is a sample customer from the Kinetic training database. If you use a
different database, select any existing customer ID from your database and
specify it as the custID input parameter.

l Click Execute.
l Note the Response Body results for customer Addison.

4. Now, test a method supporting HTTP GET call.

l Search for and select the GetList method.


l Notice the POST method is still available, however, it is disabled and marked as obsolete.
l Depending on the API version you selected, click and expand:

V1:GET /GetList

l Click Try it out.

V1: Enter the following parameters:

Parameter Value

whereClause CustNum=2 OR CustNum=3

pageSize 0

absolutPage 0

l Click Execute. The Response Body displays results for both customers.

Note that HTTP GET methods carry all parameters in their URI (RequestURL). Make sure
all individual values are encoded appropriately, when you perform custom calls. When
you build your custom method with HTTP GET support using .NET, the System.Uri class
can be used to build the URI with the correct encoding.

19 January, 2023
Kinetic REST Services Guide v.1

Business Activity Queries Help


BAQs are exposed directly through the REST APIs.

1. On the REST API Home Page, from the Menu, select Business Activity Queries.
2. By default, the list of BAQs is empty, use search to locate REST help for a specific Business
Activity Query (BAQ). Help page uses the Ice.BO.BaqDesignerSvc/List method to search for the
list of BAQs. A user performing the search must be allowed to use this method.
3. The Company displays the current Company selected for the user. If needed, select another
company from the drop-down list.
4. In API Version drop-down list, you can switch between working with Kinetic REST API Services
v.1 or v.2.
5. In this example, in the Search box, enter cust and from the drop-down list, select the COM-
CustContacts query.

6. The help page displays the available BAQ resources. You can use this page to dynamically test the
query.

V1:

Each BAQ exposes at least two endpoints that execute the BAQ (GET /) and return metadata info
(GET /$metadata). Updatable BAQs (UBAQs) also expose a PATCH / endpoint to update record(s)
and a GetNew method (GET /GetNew) to create new records. You can define initial field values
for a new record in the UBAQ's settings within Kinetic.

7. Set REST header(s).

20 January, 2023
Kinetic REST Services Guide v.1

By default, the API Key header is displayed. If you are using the REST API v.2, you must pass an
API Key with each call. Set the API Key Header or enter it manually for each call. You can add
additional headers as needed. You can add only one header of each available type. Custom
headers are not supported. Please review the Service Controls and REST Headers section above
for details on supported headers.

8. Press GET / to expand the section. Verify the API Key parameter is set. Press Try it out and then
Execute.

Review the returned service document for the BAQ.

9. Press GET /$metadata, then Try it out and Execute. Review the metadata of the BAQ service.

10. Now, select GET /Data and press Try it out. The results of the BAQ are returned.

21 January, 2023
Kinetic REST Services Guide v.1

11. In the Parameters section select the $filter field and enter CustCnt_Country eq 'USA'.

12. Press Execute. The results of the BAQ are specific to records for the country of USA. Please refer
to the Using OData Parameters article for details on using parameters in calls against Kinetic
REST API.

Calling Kinetic Services


This section documents the primary details about the Kinetic REST Services available on your server.
This information explains how the Kinetic REST Services interact with your Kinetic database. Each
Kinetic service contains these main parts:

22 January, 2023
Kinetic REST Services Guide v.1

l OData Datasources – REST uses these datasources to display and modify the data in a format
consumable by web applications.
l Methods – Use both standard and custom methods to access, add, and update data within the
main tableset for each service.

OData Datasources
The OData Datasources are compliant with the protocols for OData Version 4. Because of this, you can
access the features available with this version. It does this by running Create, Read, Update, and Delete
(CRUD) actions on specific business objects. It also performance OData query options on the collection
of business objects.

You can review the OData Version 4.0 Core Protocol on this website.

Service Directories
You use the following URLs to access the Kinetic REST Services:

V1:

l Sample directory path to all services


https://KineticServer/Kinetic/api/v1/

l Sample directory path to a specific service


https://KineticServer/Kinetic/api/v1/Erp.Bo.CustomerSvc/

l Sample directory for service metadata for a specific service


https://KineticServer/Kinetic/api/v1/Erp.Bo.CustomerSvc/$metadata

Business Activity Query (BAQ) Service Directories


You run CRUD actions on specific BAQ objects, as well as run OData query operations on business object
collections.

You can run the Create, Read, Update, and Delete actions on updatable BAQs. Standard
BAQs can only be Read.

Each BAQ resource has these features:

23 January, 2023
Kinetic REST Services Guide v.1

l OData $metadata for the BAQ; this data describes the data structure of the BAQ results.
l OData query options such as $select and $filter; these options limit the data returned by the
BAQ.
l Custom query parameters (if supported by the BAQ).
l RESTful update actions (if supported by the BAQ).
V1:

When you call a BAQ, use the following syntax:

https://[KineticServer]/[KineticInstance]/api/[VersionNumber]/BaqSvc/[BaqName]?[baq-
param]=x&[baqParam2]=y

Use the following URLs to access business activity queries (BAQs) through the Kinetic REST Services:

l Sample directory for all BAQs in the current company

https://KineticServer/Kinetic/api/v1/BaqSvc/

l Sample directory for all BAQs for a specific company

https://KineticServer/Kinetic/api/v1/BaqSvc/?Company='EPIC03'

l Sample directory for service metadata for a specific BAQ

https://KineticServer/Kinetic/api/v1/BaqSvc/COM-90daysSORel/$metadata

l Sample directory for service metadata for a specific BAQ in a specific company

https://KineticServer/Kinetic/api/v1/BaqSvc/COM-90daysSORel('EPIC03')/$/$metadata

Methods
The Kinetic REST Services support the GET, POST, PATCH, and DELETE HTTP methods. When you need
to access business activity queries (BAQs) and updatable business activity queries (UBAQs) through
HTTP, you use the GET and PATCH methods. You can then run both standard and custom methods
against the Kinetic REST Services.

Standard Methods
The standard methods require case sensitive syntax to properly execute. You can run the GetList,
GetRows, GetByID, and UpdateExt methods to display data and update the main tableset for each
service. The OData datasource also supports these additional, special parameters:

24 January, 2023
Kinetic REST Services Guide v.1

l $filter – Limits the data results through criteria you define.


l $select – Defines specific columns to display in the data results.
l $expand – Includes all the child entities in the data results.
l $top – Pages through the list of data results.
l $skip – Pages through the list of data results.
l $orderby – Sorts the data results by a value you define.
The Kinetic REST Services support the following code formats:

V1:

l application/json
l application/atom+xml
All OData URI elements are case sensitive. For your standard method calls to run properly, any field
names, $-like parameter names, and values must also be case sensitive. The following example pulls
the ‘A’ record from the ABCCodes dataset:

V1: https://KineticServer/Kinetic/api/v1/Erp.BO.ABCCodeSvc/ABCCodes?$filter=ABCCode1 eq 'A'

Notice that the request to the ABCCodes entity set, the $filter parameter, and ABCCode dataset are all
case sensitive values. You must also use ABCCode1 as a column name in this syntax because OData
does not allow to have a column on type with a name identical to the type name.

The following example uses a $filter parameter to pull a date time value:

V1:
https://KineticServer/Kinetic/api/v1/Erp.Bo.CustomerSvc/Customers/?$select=EstDate&$filter=EstDate
eq datetime'2016-02-22T00:00:00'

The $filter parameter also only works with fields that exist internally in the database. This parameter
uses where clauses for both the GetRows and GetList service calls, and these calls are translated into
stored procedure parameters.

Custom Methods
Some services have unique custom methods that serve to invoke very specific actions - for example,
GetByCustID in Customer, which allows retrieving customer records by a Customer ID. These service
methods must be called using the HTTP POST method and the application/json format.

A subset of custom methods exposed by Kinetic Services such as GetByID, GetList, GetRows,
GetBySysRowID, and GetBySysRowIDs support calling HTTP GET method. For these methods, HTTP

25 January, 2023
Kinetic REST Services Guide v.1

POST methods are still fully supported, however, they are disabled and marked as obsolete. Epicor
recommends any new testing and development is performed using HTTP GET.

See the Working with Custom Methods article for examples.

26 January, 2023
Kinetic REST Services Guide v.1

Using OData Querying


OData Querying
OData uses special parameters on URLs to do querying via REST similar to using SQL to query a
database. The URL of a service supports a couple of different patterns. You can enter a URL to identity a
Single Entity or a Entity Set. You can query for 'Parent / Child' data by navigating the relations defined
in the service. You can also apply one or more parameters to the query.

The names of tables and columns in queries are case sensitive and must match tables and
columns' names in tablesets. For example, in the query for a Customer with a CustID of
Addision, the CustID column must match the column in the tableset:

V1: https://KineticServer/Kinetic/api/v1/Erp.Bo.CustomerSvc/Customers?$filter=CustID eq
'Addison'

Querying for Entity Set vs Single Entity

Entity Set
Querying for an Entity Set is as simple as not specifying any parameters.

1. In your browser, enter this URL to get full data of all Customers in the system:

V1: https://KineticServer/Kinetic/api/v1/Erp.BO.CustomerSvc/Customers

2. The JSON response contains full customer information from the system.

Single Entity
When you want a specific item, you can query for that record by using its key fields. For example:

1. Use this resource with parameters: Customers({Company},{CustNum}).


2. In the browser enter this request URL to get data for Addison only:

V1: https://KineticServer/Kinetic/api/v1/Erp.BO.CustomerSvc/Customers('EPIC06',2)

3. The single record returned for Addison.

27 January, 2023
Kinetic REST Services Guide v.1

Addison (Customer Number 2) is a sample customer ID from the Kinetic training database.
If you use a different database, take any existing customer number from your database to
use in this query.

Strings are enclosed in single quotes (').

Navigating Relationships
Relationships exist within the Kinetic 'ZData' system that is used for generating tablesets and datasets.
These relations can be used to navigate from a parent record to its child or children. Note only the
children records are returned. To have both the parent and children returned, the $expand parameter
needs to be used.

Child Entity Set


You can get the 'children' of a record by appending the related entity to the URL.

1. Use this endpoint /Customers({Company},{CustNum})/ShipToes to get the ShipTo records for a


customer.
2. Enter this URL in your browser:

V1: https://KineticServer/Kinetic/api/v1/Erp.BO.CustomerSvc/Customers('EPIC06',2)/ShipToes

3. The results are the ShipToes for Addison.

Single Child Entity


You can get the single child of a record by appending the related entity and key(s) to the URL.

1. Use this endpoint /Customers({Company},{CustNum})/ShipToes({Company},{CustNum},


{ShipToNum}) to get data for a specific ShipTo record in Addison.
2. For the Company, enter 'EPIC06'.
3. For the CustNum, enter 2.
4. For the ShipToNum, enter '001'.
The request URL should look like this:

V1: https://KineticServer/Kinetic/api/v1/Erp.BO.CustomerSvc/Customers('EPIC06',2)/ShipToes
('EPIC06',2,'001')

5. The results are the ShipToes with ShipToNum value equal to 001 for Addison.

28 January, 2023
Kinetic REST Services Guide v.1

Using OData Parameters


Erp.BO.CustomerSvc and Ice.BO.DocTypeSvc services will be used for demonstration.

In your browser, retrieve full customer data from the Kinetic database:

V1: https://KineticServer/Kinetic/api/v1/Erp.BO.CustomerSvc/Customers

Use this base service resource URL in the REST v.1 examples below.

Note that the response is huge. In real life, you may not need all this data. Use OData parameters to
modify your requests and make them more specific to avoid excessive payloads.

Syntax rules include:

l Query parameters can be appended to a URL with an ?.


l Query parameters are prefixed with a $ character.
l Many parameters take multiple values that are separated by a comma.
l Different query parameters in the URL are appended with an &.

$select
This parameter selects specific dataset columns. It works similar to a SELECT statement in SQL

1. Add the following columns - Company, CustID, CustNum - into the $select parameter and add it
to the base service URL:

V1:
https://KineticServer/Kinetic/api/v1/Erp.BO.CustomerSvc/Customers?$select=Company,CustID,C
ustNum

2. The results include data for the requested columns only.

$filter
This parameter is equivalent of WHERE clauses in SQL:

1. Keep the $select parameter values from the previous request.

2. Add a $filter parameter - $filter=State eq 'MN'.

Your request URL should look like this:

29 January, 2023
Kinetic REST Services Guide v.1

V1:
https://KineticServer/Kinetic/api/v1/Erp.BO.CustomerSvc/Customers?$select=Company,CustID,C
ustNum&$filter=State eq 'MN'

3. Send the request. The results just include records in the state of Minnesota.

Literals Supported In $filter Functions


Go to this OData documentation page for the OData definition of primitive data types.

The following data types are supported:

Boolean filter $filter=Tip_Active eq false or Tip_Active eq true

Decimal filter Number01 lt 1.99M

Int64 filter RunTaskNum lt 9999999999999l

DateTime filter LastActivityOn eq datetime'2016-06-22T17:05:12.464Z'

Guid filter SysRowID eq guid'e830ab94-680b-49fe-882c-9f9d0117ac39'

Built-In $filter Operators and Functions


OData supports many operators such as the ones below. A complete list is at the OData specification
site.

Kinetic does not support the following operators and functions: IsOf, Any, All, mod, and
cast. The replace function is not supported in OData 4.0.

Comparison operators:

eq Equal /Suppliers?$filter=City eq 'Redmond'

ne Not equal /Suppliers?$filter=City ne 'London'

gt Greater than /Products?$filter=Price gt 20

ge Greater than or equal /Products?$filter=Price ge 10

30 January, 2023
Kinetic REST Services Guide v.1

lt Less than /Products?$filter=Price lt 20

le Less than or equal /Products?$filter=Price le 100

Logical operators:

and Logical and /Products?$filter=Price le 200 and


Price gt 3.5

or Logical or /Products?$filter=Price le 3.5 or


Price gt 200

not Logical negation /Products?$filter=not endswith


(Description,'milk')

Arithmetic operators:

add Addition /Products?$filter=Price add 5 gt 10

sub Subtraction /Products?$filter=Price sub 5 gt 10

mul Multiplication /Products?$filter=Price mul 2 gt


2000

div Division /Products?$filter=Price div 2 gt 4

Grouping operators:

() Precedence grouping /Products?$filter=(Price sub 5) gt


10

String functions:

contains contains(CompanyName,'freds')

endswith endswith(CompanyName,'Futterkiste')

startswith startswith(CompanyName,'Alfr')

length length(CompanyName) eq 19

indexof indexof(CompanyName,'lfreds') eq 1

substring substring(CompanyName,1) eq 'lfreds Futterkiste'

31 January, 2023
Kinetic REST Services Guide v.1

tolower tolower(CompanyName) eq 'alfreds futterkiste'

toupper toupper(CompanyName) eq 'ALFREDS FUTTERKISTE'

trim trim(CompanyName) eq 'Alfreds Futterkiste'

concat concat(concat(City,', '), Country) eq 'Berlin, Germany'

Date functions:

year year(BirthDate) eq 0

month month(BirthDate) eq 12

day day(StartTime) eq 8

hour hour(StartTime) eq 1

Math functions:

round round(Freight) eq 32

floor floor(Freight) eq 32

ceiling ceiling(Freight) eq 33

For GetRows/GetList operations on Kinetic services, any function is translated into a


WhereClause . As a result, all index-based functions like Substring and indexof are 1-
based.

$top
This parameter retrieves a certain selected number of records.

If the specified number of rows in the $top parameter is greater than the established row
limit, the service response is limited to the maximum number allowed by the Row Limit
setting.

32 January, 2023
Kinetic REST Services Guide v.1

1. Use the base Customer service URL and add a $top parameter with a value of 2.

V1: https://KineticServer/Kinetic/api/v1/Erp.BO.CustomerSvc/Customers?$top=2

2. Send the request. Note only two top records are returned - Addison and Barriston, if you use the
Kinetic training database.

$skip
This parameter is used with $top for paging: skip the first y-number of records and take the next z-
number of them.

1. For the $top parameter, enter 2.


2. For the $skip parameter, enter 4.
3. Send the request:

V1: https://KineticServer/Kinetic/api/v1/Erp.BO.CustomerSvc/Customers?$top=2&$skip=4

4. Only the fifth and sixth records from the Customer table are returned - Chiglease and Clarke.
Records 1-4 were skipped.

$orderby
This parameter allows setting a list of columns in either ascending or descending order:

1. Remove all previous parameters.


2. For the $orderby parameter, enter Name Asc.
3. Send the request:

V1: https://KineticServer/Kinetic/api/v1/Erp.BO.CustomerSvc/Customers?$orderby=Name Asc

The results are sorted alphabetically by Name.

$expand
Navigation was described above as the ability to walk from a parent to its child record and retrieve the
child. $expand gives the ability to return a hierarchy of parent and child in one result set.

Use nested $expand and $select parameters for retrieving complex hierarchies.

33 January, 2023
Kinetic REST Services Guide v.1

1. Use this endpoint /Customers({Company},{CustNum}) to retrieve specific customer data.

2. For Company, enter 'Epic06'. For the, CustNum enter 2.

3. Add the $expand parameter equal to ShipToes. Send the request:

V1: https://KineticServer/Kinetic/api/v1/Erp.BO.CustomerSvc/Customers
('EPIC06',2)?$expand=ShipToes

Full hierarchy is returned.

5. Now add a $select parameter to the parent record with the following values: Company, CustID,
CustNum, ShipToes.
6. Send the request:

V1: https://KineticServer/Kinetic/api/v1/Erp.BO.CustomerSvc/Customers
('EPIC06',2)?$select=Company,CustID,CustNum, ShipToes&$expand=ShipToes

Just the few columns from the Customer parent record return with the full ShipToes record.

8. Finally, add a nested $select parameter to ShipToes to retrieve ShipToNum data only.

V1: https://KineticServer/Kinetic/api/v1/Erp.BO.CustomerSvc/Customers
('EPIC06',2)?$select=Company,CustID,CustNum,ShipToes/ShipToNum&$expand=ShipToes

9. Send the request. Just the columns entered appear in the hierarchy returned.

$inlinecount (API v.1)


This parameter returns, along with the results, the total number of products in the set. It allows only
two values:

l allpages that will add odata.count property to the result.


l none (or not specified) does not return a count and can be omitted.

Any other value will result in 400 Bad Request error.

$inlinecount ignores any $top, $skip, and $expand query options, and returns the total
count of result rows across all pages including only those results matching any specified
$filter.

34 January, 2023
Kinetic REST Services Guide v.1

Getting all rows with odata.count field


1. In REST API Help, select Ice.BO.DocTypeSvc from the list of services.
2. Navigate to GET /DocTypes and press Try it out..
3. In the $inlinecount field, enter allpages and press Execute.
4. Note the odata.count parameter in the response:

{
"odata.metadata":
"https://KineticServer/Kinetic/api/v1/Ice.BO.DocTypeSvc/$metadata#Epicor.RestApi.DocTy
pes",
"odata.count": "18",
"value": [
{
        "Company": "EPIC03",
        "DocTypeID": ".doc",

Getting only one (2nd) row using $top and $skip with all rows odata.count
1. For the same endpoint as in the previous example, in the $top and $skip fields, enter 1.
2. In the $inlinecount field, enter allpages and execute again.
3. In the response, note the odata.count parameter value is not affected by $top and $skip
parameters:

{
"odata.metadata":
"https://KineticServer/Kinetic/api/v1/Ice.BO.DocTypeSvc/$metadata#Epicor.RestApi.DocTy
pes",
"odata.count": "18",
"value": [
{
        "Company": "EPIC03",
        "DocTypeID": "APM",

Displaying Data in OData Applications


Any application that can connect to OData or generate REST services can access data from an Kinetic
database through REST services. This section describes how you can display data through two example
applications – your internet browser and Microsoft® Excel®. These examples represent just a couple of
applications you can use. Review the documentation in other OData aware applications to learn how to
connect and display Kinetic data through them.

35 January, 2023
Kinetic REST Services Guide v.1

Linking to Browser
You can pull data from REST services for display in your internet browser. Verify your Secure Sockets
Layer (SSL) is currently running on your server. When you run a HTTPS connection you ensure that the
certificates are in place for both REST services and the OData connection. Once you have these items
set up, you can browse or call REST Services as you need.

When you browse to the URL on the Kinetic Application Server, you are prompted with a
security dialog box. Enter your Kinetic user account credentials to authenticate against
the REST API.

As described previously, use the following URL syntax to locate the root folder for an Kinetic REST
service:

V1: https://[KineticServer]/[KineticInstance]/api/v1/[ServiceName]/

If you want to display data from the SalesOrder service in your web browser, you would enter the
Service Root folder, followed by the Service Name:

V1: https://KineticServer/Kinetic/api/v1/Erp.BO.SalesOrderSvc/

This URL returns a JSON service document which lists the specific resources you can use with this
service. For a business object service, you will see one resource for each method and one resource for
each type of data entity. For each BAQ service, you will see one service root and one resource. You enter
this URL syntax to access a REST resource within a business object service:

https://[KineticServer]/[KineticInstance]/api/v1/[ServiceName]/[ResourceName]

For example, to display all the current sales orders within your web browser, you would enter:

https://KineticServer/Kinetic/api/v1/Erp.BO.SalesOrderSvc/SalesOrders

This example retrieves data from the SalesOrder business object. It calls the Erp.Bo.SalesOrderSvc
service and uses the GetRows method. If you wish to return data using an abbreviated list format, you
call the GetList method instead. To do this, use the List resource of the SalesOrder service:

https://KineticServer/Kinetic/api/v1/Erp.BO.SalesOrderSvc/SalesOrders/List

Displaying Service and BAQ Data in Excel®


By natively supporting OData, Kinetic REST Services allow for easy consumption from tools that
leverage the protocol. You can have a refreshable spreadsheet against a live data source. Build pivot
tables, charts against the feed for quick reports. Do the following to use REST Services to pull Kinetic
data within an Excel spreadsheet. You can then format this live data display as you need.

36 January, 2023
Kinetic REST Services Guide v.1

V1:

Odata v3 is supported by MS Excel® 2013 or higher.

If you use Excel 2010, you need to download and instal the PowerPivot add-in for Excel.
This download is available on this web page. Some of the steps you follow will be different
from what is documented in this section.

1. Launch Microsoft® Excel®.


2. In the Main menu, select the Data tab.

3. From the Menu Ribbon, select the Get Data option.

37 January, 2023
Kinetic REST Services Guide v.1

4. From the Get Data list, select the From Other Sources > From OData Feed. The OData Feed
dialog displays.

5. For the URL, enter the resource you wish to display in this Excel spreadsheet. For example:

V1: https://KineticServer/Kinetic/api/v1/Erp.BO.CustomerSvc/Customers

The following URL can be used to display data from the Customer Contacts Business Activity
Query:

V1: https://KineticServer/Kinetic/api/v1/BaqSvc/COM-CustContacts/

If you connect to the Kinetic application server for the first time, you will be
prompted to define the Authentication settings. Select the Basic tab. Enter your
Kinetic user credentials, select which level to apply these settings to, and press
Connect.

38 January, 2023
Kinetic REST Services Guide v.1

7. Press OK. The query results dialog box displays.

8. Press Load. The resource data is loaded into the current Excel spreadsheet.

39 January, 2023
Kinetic REST Services Guide v.1

You can then use table design tools to format how this data displays; please review Microsoft®
Excel® documentation for more information.

Displaying OData Feed as a PivotTable or a PivotChart


You can further analyze the real-time Kinetic resource data by displaying it in a PivotTable or A
PivotChart. Refer to the Microsoft® documentation on inserting PivotTables and PivotCharts for details.

40 January, 2023
Kinetic REST Services Guide v.1

Working with Kinetic REST API


This section illustrates some code examples for creating and updating records, connecting through
WCF, linking Updatable BAQs (UBAQs), and other functions you can customize through REST services.
Use these code examples to help you leverage REST services for your SDK projects.

While you can write your own code through C# and JSON, a number of tools are
available you can use to generate code that interfaces with Kinetic Services. For
example, one of these services is Postman; it generates runnable code in the
programming language you need.

Using Postman
Postman is a free tool for API developers to share, test, document, and monitor APIs. With Postman,
when you start doing 'POST' work against custom methods and updates, real development level calls
can be done. The use of Postman against REST is similar to the use of BLTester against the SOA
services. Additionally, the calls can be saved as a query within a larger collection and shared or used as
a test suite.

Go to this web site to download the free Postman App.

Setting Up Postman
Set up environments, variables and request headers for effective Kinetic REST API testing.

1. Launch Postman.

If prior to this you haven't defined any environments, the Current environment drop-down field
in the top right corner of the page is set to No Environment.

2. Click the Environment quick lookup (the "eye") icon next to the Current environment field.
The Manage Environments window displays.
3. Add an Environment Name. For example, Kinetic Test.
4. Optionally, you can define global and environment-specific variables. Click on an empty line in
the variables grid and add a name for your variable - for example, Host.
5. In the Initial Value field, enter the address of your server and the Kinetic appserver name
beginning with protocol. For example, https://KineticServer/KineticTest. You can now use this
variable in your request URLs in the following format: {{Variable Name}} - in this example,
{{Host}}.

41 January, 2023
Kinetic REST Services Guide v.1

Add another environment and define a different value for the same variable - for
example, https://KineticServer/KineticDev. The value of a variable in the same HTTP
requests will change depending on the selected environment. So you can easily switch
from a testing environment to development to see how your requests go through.

6. In the Builder section of the Postman screen, select the HTTP method and enter the URL of your
request. For example:

V1 {{Host}} /api/v1/Erp.Bo.SalesOrderSvc/List

This will get you the list of all sales orders in the system.

7. Navigate to the Authorization tab and select the type of authentication for the Kinetic user.

Select Basic Auth if you want to use Basic Authentication. Then enter user name and password of
the Kinetic user on whose behalf you are accessing the application server. For example,
epicor/epicor.

8. Navigate to the Headers tab. Select an empty line to add a new header.
9. In the Key field, start typing content and select Content-Type from the provided options.
10. In the Value field, enter application/json. This defines the type of sent content.
11. Add the Accept header with the application/json value to define the type of content in the
response.
You are now able to send requests to the Kinetic REST API. Proceed to the next steps to perform some
standard CRUD operations with Kinetic data.

Executing a GET
1. Enter this URL to invoke a GetRows method for the SaleOrder service:

V1 {{Host}}/api/v1/Erp.Bo.SalesOrderSvc/SalesOrders

2. On the Authentication tab, expand Type and select Basic Authentication. It should contain the
credentials you have specified for your environment.
3. Press Send. Note the results are SalesOrders.
4. Press the Headers tab in the response. Note the Context Header information for BPM.

Executing a POST

42 January, 2023
Kinetic REST Services Guide v.1

1. Set the HTTP method for the URL to POST.


2. For the URL, enter:

V1 {{Host}}/api/v1/Erp.BO.CustomerSvc/Customers

3. Click on Body and add this JSON code to it:

{      
"Company": "EPIC06",      
"CustID": "MYTEST",      
"CustNum": 0,      
"Name": "My test customer",      
"TerritoryID":  "US MID"    
}

4. Press Send. Note the newly created record with a new CustNum in the response.

Diagnosing an Error
Many times, the REST APIs provide helpful information. If this isn't the case, you need to review the
results in the Windows Event Viewer. Kinetic has a 'Flight Data Recorder' log.

Please go to the System Management > Working with System Management >
Performance Tuning Guide > Microsoft Tools > Event Viewer article in Classic Interface
Application Help for details on using Windows Event Viewer.

1. Press Send to send a request.


2. If an Error Message is returned, click on the Windows Start button and enter Event Viewer in the
search text box. Select Event Viewer from the list.
3. In the Window Event Viewer, expand Applications and Services Logs.
4. Select Epicor App Server.
5. Select the error. Note the description of the exception is displayed.

Creating a New Customer


The following example illustrates how to add a new customer to the Kinetic database. Use this code as
a base example for creating new records in the Kinetic database via REST:

V1:

43 January, 2023
Kinetic REST Services Guide v.1

POST https://KineticServer/Kinetic/api/v1/Erp.Bo.CustomerSvc/Customers HTTP/1.1


Host: KineticServer
Content-Type: application/json
Authorization: Basic 
Cache-Control: no-cache
{
      "Company": "EPIC06",
      "CustID": "MYTEST",
      "CustNum": 0,
      "Name": "My test customer",
      "TerritoryID":  "US MID"
    }

Now when you save this record, the CustNum value becomes the primary key for the new customer
record. You can then later retrieve this customer number through a GET HTTP method. For example:

V1: GET https://KineticServer/Kinetic/api/v1/Erp.Bo.CustomerSvc/Customers ('EPIC06',47) HTTP/1.1

Updating a Customer
The following code example illustrates how you can update an existing customer record. Use this code
as a base example for updating existing records.

V1:

PATCH https://KineticServer/Kinetic/api/v1/Erp.Bo.CustomerSvc/Customers ('EPIC06',47)


HTTP/1.1
Host: KineticServer
Content-Type: application/json
Authorization: Basic
{
      "Company": "EPIC06",
      "CustNum": 47,
      "Name": "Another Name for test customer"
    }

Deleting a Customer
This code example removes an existing customer from the database.

V1:

DELETE https://KineticServer/Kinetic/api/v1/Erp.Bo.CustomerSvc/Customers('EPIC06',47)
HTTP/1.1
Host: KineticServer
Content-Type: application/json
Authorization: Basic

44 January, 2023
Kinetic REST Services Guide v.1

Updating a Child Entity


You can also update the entities for records. This C# code example shows you how to update entities
within user code records.

V1:

public void CreateUserCode()


{
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, ServiceUrl
+ "/Ice.Bo.UserCodesSvc/UserCodes");

            request.Content = new StringContent(JsonConvert.SerializeObject(new


{
                    Company = "EPIC03",
                    CodeTypeID = "type1",
                    CodeTypeDesc = "type",
                    LongDesc = "Description of ud type",

                    UDCodes = new[]
{
new { 
                                Company = "EPIC03",
                                CodeTypeID = "type1",
                                CodeID = "my UD code",
                                CodeDesc = "my code desc",
                             }
                    }
                }),
                Encoding.UTF8,
"application/json");
            HttpResponseMessage response = client.SendAsync(request).Result;
        }

Deleting child User Code; Leaving User Type intact


This C# code example illustrates how you remove a user code, but do not remove a user type.

V1:

string parentKeystr = "Company='EPIC03',CodeTypeID='type1'";

string childKeystr = "Company='EPIC03',CodeTypeID='type1',CodeID = 'my UD


code'";

            request = new HttpRequestMessage(HttpMethod.Delete, ServiceUrl + String.Format


("/Ice.Bo.UserCodesSvc/UserCodes({0})/UDCodes({1})", parentKeystr, childKeystr));

            response = client.SendAsync(request).Result;

45 January, 2023
Kinetic REST Services Guide v.1

Executing a BAQ
You can use custom code to run a specific Business Activity Query (BAQ) and display specific records
from that query. Use the following URL format to run a specific BAQ:

V1: https://[KineticServer]/[KineticInstance]/api/v1/BaqSvc/BaqName?param=[ParamValue]

To run this query, you substitute the BAQName value with the Query ID for the query you wish to access
and Company - with a Company ID.

The optional param value defines any additional parameters you wish to run against the query. These
parameter values are specified through a query string. Any Date parameters must be specified in the
ISO format (‘2016-12-01’) illustrated in this example. If you want to display a value list, you can specify it
several times. For example, if you have a value list parameter defined in the BAQ Designer named
listParam, your query string uses the following syntax:

listParam=value1&listParam=value2&listParam=value3

You can also run the $filter OData parameters against BAQ results. These filters are added to the URL as
query execution parameters. For example:

V1: https://[KineticServer]/[KineticInstance]/api/v1/BaqSvc/testREST?tt=20&$filter=not (startswith(Tip_


TipText,'Use') or startswith(Tip_TipText,'To'))

This BAQ named testREST is created for the Ice.Tip table and selects all rows where TipText does not
start with Use or with To.

Working with Updatable BAQs (UBAQs)


This article explains how you can add, update, and delete records with UBAQs via REST.

Creating a New Record


The following example illustrates how to create an empty updatable Business Activity Query (UBAQ)
row where a new record can be entered and submitted to the database. Use the following URL format
to create a new record:

V1: https://KineticServer/Kinetic/api/v1/BaqSvc/[uBAQName]/GetNew - and change uBAQName to the


Query ID of the uBAQ you use.

For example:

V1:

46 January, 2023
Kinetic REST Services Guide v.1

GET https://KineticServer/Kinetic/api/v1/BaqSvc/Udtip/GetNew HTTP/1.1


Host: KineticServer
Authorization: Basic

If you defined initial expressions for your UBAQ's displayed fields, when you call the GetNew method,
the fields of the new record are filled with these values. For example, if the initial expression of the Tip_
Company field is mapped to the Current Company BAQ Constant, the newly created Tip record will
have the current Company ID in this field - for example, "Tip_Company": "EPIC06".

Updating a Record
Depending on the API version, use the PATCH /Data (API v.2) or PATCH / (API v.1) endpoint to update a
record. You specify the values of updatable fields in the request body using JSON format. For example:

V1:

PATCH https://KineticServer/Kinetic/api/v1/BaqSvc/ Udtip HTTP/1.1


Host: KineticServer
Authorization: Basic 
Content-Type: application/json
{
      "Tip_Company": "EPIC03",
      "Tip_MfgSys": "EP",
      "Tip_TipNum": 1,
      "Tip_Active": true,
      "Tip_TipTitle": "2121",
      "Tip_TipText": "####Changed TipText of tip",
      "Tip_ShowNum": 0
      }

Deleting a Record
You can also delete records using a UBAQ. First, you need to configure the mapping for RowMod in the
uBAQ definition:

1. From the main menu, navigate to System Management > Business Activity Queries > Business
Activity Query.
2. Load the uBAQ you want to use for deleting records.
3. Navigate to the Update > Update Processing sheet.
4. In the Processing Method pane, select the BPM Update radio button. The BPM Update
Processing section activates.
5. The Select Business Object window displays. Select the business object you want from the
Suggested business objects list.

47 January, 2023
Kinetic REST Services Guide v.1

6. In the Query to Object Column Mapping grid, add a new line for the RowMod field of the BO
table and map it to an expression - for example, Tip.RowMod = ttResult.RowMod.
7. Press Save.
When the mapping is defined, you can set RowMode to D (delete) in the PATCH request to delete the
record. For example:

V1:

PATCH https://KineticServer/Kinetic/api/v1/BaqSvc/ Udtip HTTP/1.1


Host: KineticServer
Authorization: Basic 
Content-Type: application/json
{
      "Tip_Company": "EPIC03",
      "Tip_MfgSys": "EP",
      "Tip_TipNum": 1,
      "RowMod": "D"
      }

Working with Custom Methods


You can invoke non-standard service methods via REST. Custom methods can be used with the GET and
POST verb in code. By default, HTTP GET is enabled in both versions of Kinetic REST API (v.1 and v.2) for
methods that do not modify data, such as GetByID, GetList, or GetRows. While HTTP POST methods
are still fully supported for these custom methods, they are marked as obsolete. Epicor recommends
any new testing and development is performed using HTTP GET.

HTTP POST custom methods must use the application/json format. Because of this, they contain input
parameters sent as JSON object properties. The results returned from the method call are sent in a
JSON object. Within this object, the returnObj setting contains the return value and parameters –
including the Out and ByRef parameters. Null values do not return from the method query.

Note the following principles when specifying HTTP GET method parameters:

l HTTP GET method carries all parameters in URI, for example:

V1: https://KineticServer/Kinetic/api/v1/Ice.BO.TipSvc/GetByID?mfgSys=EP&tipNum=123

l The individual values must be encoded correctly. In .NET Framework, the System.Uri class can
be used to build the URI with the correct encoding. For example, 'A & B' needs to passed as 'A
%26 B'.

48 January, 2023
Kinetic REST Services Guide v.1

l Complex parameters such as datasets or other classes need to be serialized to JSON, for
example:

V1: https://KineticServer/Kinetic/api/v1/Ice.BO.SomeService/GetData?request={ "viewId":


"Ice.UIRpt.ChgLogReport", "properties": { "layers": [ "MyLayer", "MyLayer2" ] } }

The request parameter represents a class, defined as per the below example:

public class MyClass


{
public string ViewId { get; set; }
public MyChildClass Properties { get; set; }
    }

public class MyChildClass


{
public string[] Layers { get; set; }
    }

l To specify arrays using IEnumerable<>, IList<>, or List<> parameter types, make sure to specify
each value separately using the same parameter, for example:

V1: https://KineticServer/Kinetic/api/v1/Ice.BO.SomeService/GetData?value=A&value=B&value=C

Example 1 - HTTP POST


V1:

POST https://KineticServer/Kinetic/api/v1/Ice.BO.LangTranSvc/UpdateSingleTranslation/
Request body {"pcLanguage" : "rus", "pcProgram" : "qq", "pcText" : "test", "pcTranslation" :
"ццццц", "pcProgTranslation": "яяяяя"}
Response 
{
      "parameters": {
        "bSeccess": true
      }
    }

Example 2 - HTTP POST


V1:

POST https://KineticServer/Kinetic/api/v1/Ice.BO.TipSvc/GetNewTip/
    Request {"mfgSys":"EP","ds":{"Tip":[]}}
    Response 
{

49 January, 2023
Kinetic REST Services Guide v.1

      "parameters": {
        "ds": {
          "Tip": [
{
             "Company": "EPIC03",
              "MfgSys": "EP",
              "TipNum": 0,
              "Active": true,
              "TipTitle": "",
              "TipText": "",
              "SystemFlag": false,
              "SysRevID": 0,
              "SysRowID": "00000000-0000-0000-0000-000000000000",
              "AllCompanies": false,
              "BitFlag": 0,
              "RowMod": "A",
            }
          ]
        }
      }
    }

Example 3 - HTTP GET


V1: https://KineticServer/Kinetic/api/v1/Ice.BO.TipSvc/GetBySysRowID?id=e830ab94-680b-49fe-882c-
9f9d0117ac39

{
  "returnObj": {
    "Tip": [
{
        "Company": "",
        "MfgSys": "EP",
        "TipNum": 13,
        "Active": true,
        "TipTitle": "Quick Calendar Access",
        "TipText": "You can quickly access calendars by right-clicking any Date field.",
        "SystemFlag": true,
        "SysRevID": 4509285190,
        "SysRowID": "e830ab94-680b-49fe-882c-9f9d0117ac39",
        "AllCompanies": true,
        "BitFlag": 0,
        "RowMod": ""
      }
    ],
    "ExtensionTables": []
  }
}

Example 4 - HTTP GET


V1: https://KineticServer/Kinetic/api/v1/Ice.BO.TipSvc/GetByID?mfgSys=EP&tipNum=23

50 January, 2023
Kinetic REST Services Guide v.1

{
  "returnObj": {
    "Tip": [
{
        "Company": "",
        "MfgSys": "EP",
        "TipNum": 23,
        "Active": true,
        "TipTitle": "Send e-mail with Right Click",
        "TipText": "You can quickly send a contact e-mail from the Customer Tracker.  Do
this by right clicking on the contact name and selecting \"Send email\" from the context
menu.",
        "SystemFlag": true,
        "SysRevID": 4509285196,
        "SysRowID": "f605f9f0-06a9-4a83-b90c-9f9d0117ac39",
        "AllCompanies": true,
        "BitFlag": 0,
        "RowMod": ""
      }
    ],
    "ExtensionTables": []
  }
}

Using Custom Headers


You can create custom headers to adjust server call behavior. These headers implement the
ICallHeader interface from Epicor.ServiceModel and are used the same way ICallHeader is used in WCF.
Custom headers are sent as HTTP request/response headers. Request headers are always in JSON
regardless of the specified Content-Type. Response headers are also in JSON, except for the CallerTrace
header, which is a base64-encoded string.

Below is the list of available custom headers with examples.

API Key Header


In REST v.2, sends the API Key that identifies the calling application. API Key is a required parameter for
each request sent against the Kinetic REST API v.2. It can be specified in a request header - for example:

GET /Kinetic/api/v2/odata/EPIC06/Erp.BO.CustomerSvc/Customers?= HTTP/1.1


Host: KineticServer
Content-Type: application/json
Authorization: Basic bWFuYWdlcjpFcGljb3IxMjM=
x-api-key: atI7eSN1f1Uuao8gsgtDeWzRv4LiC9OotpUbzFTAPN7mk

51 January, 2023
Kinetic REST Services Guide v.1

You can also specify an API Key as a querystring parameter. For details, go to the Using
Custom Request Parameters article of this guide. Select a method that better suits the
type of the integration with Kinetic.

CallSettings Header
Used to specify additional settings for a call - for example, to allow the client to specify both Company
and Plant information in a request.

The Company and Plant values in the CallSettings header will be overridden by the
corresponding values specified in the request URL and/or query parameter(s).

C# Example

private static HttpClient client = new HttpClient();


    ICallHeader hdr = new CallSettings("EPIC06", "MfgSys", "", "");
    client.DefaultRequestHeaders.Add(hdr.Name, JsonConvert.SerializeObject(hdr));

Http Header Example


Header name: CallSettings

Header value: {"Company":"EPIC06","Plant":"MfgSys","Language":"","FormatCulture":"" }

SessionInfo Header
SessionInfo header sends SessionID to the server. It can be obtained, for example, from the Login
method of the SessionMod service:

V1:

POST https://KineticServer/Kinetic/api/v1/Ice.Lib.SessionModSvc/Login HTTP/1.1


Host: KineticServer
Authorization: …
Content-Type: application/json

The result of the call will contain the SessionID to use in the session:

52 January, 2023
Kinetic REST Services Guide v.1

{
    "returnObj": "232a2868-cf60-46f1-8dba-1ac53328a66b"
}

SessionInfo header will look like this:

SessionInfo: {"SessionID": "232a2868-cf60-46f1-8dba-1ac53328a66b"}

Now it can be sent with each REST request during this session.

When a session is no longer needed, the Logout method of the SessionMod service should be called:

V1:

POST https://KineticServer/Kinetic/api/v1/Ice.Lib.SessionModSvc/Logout HTTP/1.1


Host: KineticServer
Authorization: …
Content-Type: application/json
SessionInfo: {"SessionID": 232a2868-cf60-46f1-8dba-1ac53328a66b"}

OnBehalfOfToken Header
In a REST call, this header allows a user with impersonation rights accomplish tasks on behalf of other
users in Kinetic.

If for any reason a task needs to be run on behalf of another user, add the OnBehalfOfToken header
and specify the user on whose behalf you will run this task. For example, you have primary user Agent
for call authorization, but you need to make this call on behalf of user Epicor. Add the below value to
the OnBehalfOfToken header:

Key Value

OnBehalfOfToken {"Username":"Epicor"}

Your request may look like this:

V1:

POST https://KineticServer/Kinetic/api/v1/Ice.BO.UserFileSvc/GetUserFile HTTP/1.1


Host: Kinetic
Authorization: Basic …
Content-Type: application/json
OnBehalfOfToken: {"Username":"Epicor"}

53 January, 2023
Kinetic REST Services Guide v.1

Note the response: your call is accomplished on behalf of user Epicor. Top 10 lines of the response to
the above request:

{    
"returnObj": {        
"UserFile": [            
{                
    "UserID": "Epicor",                
    "Name": "Epicor",                
    "Address1": "",                
    "Address2": "",                
    "City": "",                
    "State": "",

The primary user (e.g. Agent) must be allowed Session Impersonation in User Account
Security Maintenance.

License Header
Normally, when a REST call is sent to Kinetic services, a standard Default User license is granted for the
session. However, you can specify a different license in the call header. In an integration scenario, you
can use a Web Services User license for the external REST calls - from, for example, a website, or a web
application. Here's an example of a license header:

V1:

GET https://KineticServer/Kinetic/api/v1/Erp.BO.SalesOrderSvc/SalesOrders HTTP/1.1


Host: Kinetic
Authorization: Basic …
License: {ClaimedLicense: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"}

The GUIDs of the most common licenses are:

DefaultUser = "00000003-B615-4300-957B-34956697F040"

WebService = "00000003-9439-4B30-A6F4-6D2FD4B9FD0F"

You can obtain other specific license GUIDs from your .lic license file.

Turn on the restapi, license, and session traces in the AppServer.config file and then
check ServerLog.txt to verify the type of license granted for your calls. Go to the
Server Log Customization topic in the Classic Interface Application Help (System
Management > Working with System Management > Performance Tuning Guide >

54 January, 2023
Kinetic REST Services Guide v.1

Customize Logs > Server Log Customization) for details on server log tracing
options.

Trace Flags and Caller Trace Headers


Allow returning server traces stored in OperationTracer to the client. If the TraceFlags request header is
specified as empty class, like below:

V1:

GET https://KineticServer/Kinetic/api/v1/Erp.BO.SalesOrderSvc/SalesOrders HTTP/1.1


Host: Kinetic
Authorization: Basic …
License: {ClaimedLicense: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"}

The response will contain the CallerTrace header with OperationTracer content defined by trace flags
on the server side (in the AppServer.config file).

The CallerTrace response header contains base64-encoded data:

Callertrace PD94bWwg-
dmVyc2lvb-
j0iMS4wIiBl-
bmNvZGluZz0idXRmLTE2Ij8+DQo8T3AgVXRjPSIyMDE3LTEwLTEzVDE5OjM4OjUyLjU2NzY2OTJaIiBhY3Q9IiIgZHVy-
PSIyNzYuNzM5NyIgY2x-
pPSIiIHVzcj0iIiBtYWNoaW5lPSJSTTA2MTctUEYwUlM5WUciIHBpZD0iOTU0MCIgdGlkPSIxMzAiIC8+

To get its text content, use Base64 decode functions. For example, in C#, the header can be decoded as:

byte[] data = Convert.FromBase64String(encodedTrace);


string trace = Encoding.UTF8.GetString(data);

After decoding, the header content will look like this:

<?xml version="1.0" encoding="utf-8"?>


<Op Utc="2017-10-13T19:38:52.5676692Z" act="" dur="276.7397" cli="" usr="" machine="RM0617-
PF0RS9YG" pid="9540" tid="130" />

There is a possibility to specify additional flags that you want to see in the header. For example, add
new flags in the FlagList attribute of the TraceFlags header:

V1:

55 January, 2023
Kinetic REST Services Guide v.1

GET https://KineticServer/Kinetic/api/v1/Ice.BO.TipSvc/Tips HTTP/1.1


Host: KineticServer
Authorization: Basic …
License: {ClaimedLicense: "{XXXXXX3-XXXX-XXXX-XXXX-XXXXXXXXXXXXX"}
TraceFlags: {FlagList:["trace://ice/fw/license", "profile://ice/fw/tableset"]}

Now, the CallerTrace will contain additional traces. The response to the above request (after decoding)
will look like this:

<?xml version="1.0" encoding="utf-8"?>


<Op Utc="2017-10-13T19:49:43.3950234Z" act="" dur="230.2327" cli="" usr="" machine="RM0617-
PF0RS9YG" pid="9540" tid="99">
<License msg="Obtaining license for session type:'CRM' ID='XXXXXX3-XXXX-XXXX-XXXX-
XXXXXXXXXXXXX'" />
<License msg="Granted 'CRM' license #1 of 30000." />
<License msg="Claim on license extended until: SessionID:19247e63-a49e-4996-a173-
110eaba1cc78 LicenseExpiration: 10/13/2017 8:04:00 PM" />
<Sproc name="[Ice]._ZFW_Tip_GetRows" duration="65.8362" />
<RowEvent table="Tip" method="AfterGetRows" rows="100" duration="0.0159" />
<RowCount tableset="TipTableset" count="100" />
</Op>

Not all existing traces from AppServer.config are added to the OperationTracer data. Some flags are
only used in server-side logging. Such traces will not be returned in this CallerTrace header, even if they
are specified.

Trace size in the response can be quite large if server operation was lengthy and traces
are very detailed. There are limits for headers' size in IIS (16 KB) that will not allow such
long headers. Therefore, the limits must be adjusted if a very long CallerTrace is expected.
Alternately, reduce the list of trace flags in the request.

ContextHeader Header
This header allows sending and receiving additional call information. It is primarily used by Business
Process Management (BPM). Here is an example of the ContextHeader response header:

contextheader 
{"Context":{"BpmData":[{"Password":"","ButtonValue":0,"Character01":"",
"Character02":"","Character03":"","Character04":"","Character05":"",
"Character06":"","Character07":"","Character08":"","Character09":"",
"Character10":"","Character11":"","Character12":"","Character13":"",
"Character14":"","Character15":"","Character16":"","Character17":"",
"Character18":"","Character19":"","Character20":"","Number01":0.0,
"Number02":0.0,"Number03":0.0,"Number04":0.0,"Number05":0.0,
"Number06":0.0,"Number07":0.0,"Number08":0.0,"Number09":0.0,
"Number10":0.0,"Number11":0.0,"Number12":0.0,"Number13":0.0,

56 January, 2023
Kinetic REST Services Guide v.1

"Number14":0.0,"Number15":0.0,"Number16":0.0,"Number17":0.0,
"Number18":0.0,"Number19":0.0,"Number20":0.0,"Date01":null,
"Date02":null,"Date03":null,"Date04":null,"Date05":null,"Date06":null,
"Date07":null,"Date08":null,"Date09":null,"Date10":null,"Checkbox01":false,
"Checkbox02":false,"Checkbox03":false,"Checkbox04":false,"Checkbox05":false,
"Checkbox06":false,"Checkbox07":false,"Checkbox08":false,"Checkbox09":false,
"Checkbox10":false,"ShortChar01":"","ShortChar02":"","ShortChar03":"",
"ShortChar04":"","ShortChar05":"","ShortChar06":"","ShortChar07":"",
"ShortChar08":"","ShortChar09":"","ShortChar10":"",
"SysRowID":"a88bb7c0-7cff-4432-800a-84f56829df08","RowMod":"",
"SpecifiedProperties":"AAAAAAAAAAAAAQ==","UserDefinedColumns":{}}],
"CallStack":[],"CallState":[],"Client":[{"ClientType":"","ProcessId":"",
"AssemblyName":"","CustomizationId":"","CurrentUserId":"Epicor","CurrentCompany":
"EPIC06","CurrentPlant":"MfgSys","CGCCode":"","SysRowID":"12a3f052-abaf-4803-9752-
eb921c1f8fa4",
"RowMod":"","SpecifiedProperties":"/wE=","UserDefinedColumns":{}}],"ClientHandler":[],
"InfoMessage":[],"ExtensionTables":[]}}

Creating Web Applications Using REST Services


You may use REST services for creating and modifying web applications. In this workshop you will build
a single page web application that can search for Customer records in Kinetic using REST Services.

While we are using Customer as an example service the application can be easily modified to search for
any type of business object and perform different types of searches. You may use the knowledge you
gain from this workshop to try and further modify the application to search other types of business
object such as Parts, Vendors, Orders, or search through the results of a BAQ.

Setting up the environment


Make sure you have installed the following programs and the sample application code:

l Download Visual Studio Code here.


l Download Postman here.
l In the online version of the guide, you can download the pre-written code for the app.

Running the sample application


Since this workshop is about learning what you can do with Kinetic REST services we've written most of
the JavaScript, CSS, and HTML code for you already. Before we start working on the code, let's just run
the scaffolded application and see what it looks like.

57 January, 2023
Kinetic REST Services Guide v.1

1. On your computer, open File Explorer and navigate to RestWebApp\1.RestWebApp - Template.


2. Double click index.html to open the web page in your browser. As you can see this application is
just a simple search page. It has a Title, a Search Box, and space below to show your search
results.
3. Leave the web page open in your browser and proceed to the next step.

Reviewing the application code


Before you make any changes, take a look at the application code. In addition to the information in this
section you can find more details about how the application works in comments within index.html,
app.css, and most importantly app.js.

1. Open Visual Studio Code.


2. Open the Project folder in Visual Studio Code by navigating to the File > Open Folder menu. In
the RestWebApp directory, select the 1.RestWebApp - Template folder. If necessary, use the full
code of the sample application from the 2.RestWebApp - Full Code folder for reference.
3. Review the contents of the Project folder:

l index.html – Contains all html for the project.


l node_modules\ – Contains libraries the project depends on including Vue.js, JQuery, and
Bootstrap.
l scripts\app.js – Contains the application’s JavaScript.
l styles\app.css – Contains custom CSS styles for the application.
4. Open scripts\app.js by double clicking on the file in the Explorer panel on the left-hand side of
Visual Studio Code.

Vue.js, a lightweight web framework, has been used to simplify writing data to the web page
after it is loaded from REST. This may seem complicated, but it's simpler than using JQuery or
plain JavaScript to update the page with data.

App.js contains a single JavaScript object, the Vue Object, which contains all of the data you will
display on the web page as well as all the methods used to call the REST services to load data.

5. Press Ctrl-F to activate the Find dialog and search for new Vue(.The Vue object contains three
main elements:

l el – This tells Vue what HTML element bind data within. In our case it is a <div> with
id="app".
l data – Each data element we want to display on the page, or retrieve from user input is a
property of the data object.

58 January, 2023
Kinetic REST Services Guide v.1

l methods – Each function we want the UI to be able to call, such as searching for data in
the rest service, is contained within the methods object.
6. Open index.html by double clicking the file in the Explorer panel.

l Press Ctrl-F to activate the Find dialog and search for {{appTitle}}. Vue.js uses
{{mustache}} syntax to inject data into the web page as it is updated. Each place you see a
{{…}} in the index.html you can inject data into the web page. Each {{variableName}} in
index.html should have a corresponding variable in the data object in app.js. Changing the
value in the data object will automatically update the page.

Additionally, notice that there are other v-xxxx tags such as v-model, v-if, v-
on, v-for, etc. These special tags let Vue.js interact with the page in other
ways to retrieve input from the user, hide and show page elements, send
events such as typing and clicking events, and loop through data for display.

7. Switch back to the app.js file which should be open in a tab in VSCode.

8. Press Ctrl- F to activate the Find dialog and search for appTitle. The code should look like this. If
you want to change the title of the application, update this variable and reload the web page.

data: {
    appTitle: 'Awesome REST App',
   …
   }

9. Change the appTitle to Customer Search.


10. Save the file.
11. Return to your browser window, where index.html should still be open and Refresh the page.
The application title should now say Customer Search.

Creating and testing the Search REST call in Postman


Now that you have made a simple change to the application, you can move on to hooking up REST
services to search for Customers. Before you add code into your web application to call the rest services
it is convenient and useful to first test out the calls you want to make in a testing application such as
Postman or the Kinetic REST Help.

Postman has the added benefit of generating working code in a variety of programming languages so in
this section you will create a Customer business object search call in Postman, test it, and then
generate JavaScript code that you can copy & paste into our Web Application to get started quickly.

59 January, 2023
Kinetic REST Services Guide v.1

1. Leave your browser and Visual Studio Code running.


2. Open the Postman App.
3. Add a request to the Customer service for a list of customer objects and filter the list by
Customers with CustID that start with "A":

V1: {{Host}}/api/v1/Erp.Bo.CustomerSvc/Customers?$filter=startswith(CustID ,'A')&$select=CustID

4. Press Send and confirm that the query works. The query works, but it only returns the CustID
column and it would be better for our application if we could search on both CustID and the
Customer Name.
5. Remove the &$select=CustID from the query. Our REST query now looks like this:

V1: {{Host}}/api/v1/Erp.Bo.CustomerSvc/Customers?$filter=startswith(CustID ,'A')

6. Press Send to test the new query. Now you get a list of all customers where CustID starts with A;
the response includes all columns for customer.
7. To enable the query to search for customers by Name, add the following to the end of the query:
" or startswith(Name, 'A')". Make sure to include the space at the beginning, and exclude the ""
marks.
8. Press Send to test the new query. Now you can see the new query searches for customers who
have either a Name or a CustID starting with A.
9. If you want the query results to be ordered by the Customer Name, add the following to the end
of the query: &$orderby=Name.
10. Press Send to test the new query. The query should now look like below. It searches for a
customer by Name or ID and returns a list of customers ordered by Name:

V1: {{Host}}/api/v1/Erp.Bo.CustomerSvc/Customers?$filter=startswith(CustID ,'A') or startswith


(Name, 'A')&$orderby=Name

11. Click drop-down button next to the Save button and choose Save As. A Save Request dialog
displays.
12. Set the Request Name to Customer Search.
13. In the Or create new collection box enter Kinetic Rest Web App.
14. Press Save. You've now saved your new customer search query into a new collection, so it is
easier to find in the future. It can be useful to keep a collection of queries for your application
while you are developing it that you can return to modify and test.

60 January, 2023
Kinetic REST Services Guide v.1

Generating Code in Postman


Now that we know what request we want to send in our web application and we have tested that it
works we can use Postman's code generation option to create a JavaScript code sample which we can
use as a starting place in our Web Application.

1. Still in Postman, with our Customer Search query open locate the Code link in the page and
select it. This option is located below the Save button on the far right and is in small orange text.
The Generate Code Snippets dialog box displays.
2. Open the language drop-down at the top left. Notice that there are a wide variety of languages
that you can generate a sample code snippet in such as Java, Python, Swift, and of course
JavaScript. Postman can help you get started writing code in many languages to talk to our REST
services.
3. Select JavaScript > JQuery AJAX from the drop-down list. A code snippet showing how to run
our Customer Search query in JavaScript is shown.
4. Select all the text (Ctrl-A), then click Copy to Clipboard.

Adding the Postman sample code to the web application


Now that you have a working code sample for running a customer search you can paste that example
code into the web application and modify it to wire up the search input and results display in the
application.

1. Return to Visual Studio Code and open scripts/app.js


2. Locate the Search function located at about line 64. The search function is located within the
methods object. As discussed earlier any function placed within methods can be called from the
web page by Vue.js. The starter code sample is set up to call the search method any time the user
types something into the search input box.
3. In the Search method where it says /// Place the code from POSTMAN Here paste the code you
copied to the clipboard. Your pasted code should look something like this. There are two main
parts:

l the settings variable which contains the URL, all of the rest headers, etc.

V1:

var settings = {
"async": true,
"crossDomain": true,
"url":
"https://KineticServer/Kinetic/api/v1/Erp.Bo.CustomerSvc/Customers?%24filter=sta
rtswith(CustID%20%2C'A')%20or%20startswith(Name%2C%20'A')&%24orderby=Name",

61 January, 2023
Kinetic REST Services Guide v.1

"method": "GET",
"headers": {
"content": "application/json",
"accepts": "application/json",
"authorization": "Basic ",
"cache-control": "no-cache",
"postman-token": "  "
  }
}

l The $.ajax call will run the REST request and write the results to the browser's JavaScript
console when it returns.

$.ajax(settings).done(function (response) {
console.log(response);
});

4. Save app.js. After you have updated the search method you can run the application and verify
that typing something into the search box runs our sample query. It won't yet show results in the
user interface, but you can use the JavaScript debugger to verify that the REST call is sent, and
the response is written into the JavaScript console.
5. Return to your browser and verify the application is still running.
6. Press F12 to open Developer tools in your browser and resize it so you can see all of the tabs at
the top. You can use the developer tools to find issues in our web application, monitor the
network calls it makes as it tries to run our REST request, and view errors and information
messages in the console. For now, we want to look at the Network tab and the Console.
7. Click on the Network tab in Developer tools window. The network tab lets us see each network
request made by the web page. That includes loading JavaScript files, images, and critically calls
from the application to REST services.
8. Click on the Console tab in developer tools window.
9. Refresh the browser window to load the latest version. As you can see when you refresh the web
page the network panel records each network request as it loads the files required by the
application. Now you can try to type something into the application and see if the REST request
is run in the Network panel.
10. In the web page type any character into the search box. If the application is working correctly,
two things should happen in Developer tools:

l A new event should appear in the network panel showing the REST request being run. You
can click on the name to view the REST request and inspect what was sent and what was
returned.

62 January, 2023
Kinetic REST Services Guide v.1

l Because in app.js the response method runs console.log(response) a new Object should
appear in the JavaScript in Developer tools showing what was sent back from Kinetic. This
is the code that runs and retrieves the results in app.js:

$.ajax(settings).done(function (response) {
console.log(response);
});

Display the Search Results on the Web Page


You are now running a REST query when the user types a search, but the results are not shown on the
page. You will need to modify the response function to take the results and bind them to a data
element which you can use to show results on the web page.

1. Leave your browser running and return to Visual Studio Code.


2. Open app.js.
3. Press Ctrl-F to open the Find dialog and search for data: {. Just like the appTitle we have created
other variables in the data object to help show the search results:

l query is automatically filled out with whatever query the user has typed in.
l searching is set to true while the search is running and false when it's done. This is used to
show and hide an animation while the search is in progress.
l searchResults is an array that is bound to the search results table in the UI. If we add data
into the array a table will appear in the UI to show the data.
4. Press Ctrl-F to open the Find dialog and search for $.ajax.

When the $.ajax call is completed to our REST service it will then call the done() function. You
need to modify this function to set the searchResults array to the data sent back from REST. To
do that you need to make two changes.

An important point about Vue.js is if you want to access any of the data variables such as
data.searchResults within a Vue method that data element is accessible through the this
variable. At the top of the method you can see us set this.searching = true which sets the
data.searching value to true.

In a callback, such as the $ajax().done() function we need to tell JQuery to pass a reference to
the data object, this, so it is available inside of the done function using the bind(this) function.

5. Locate the last line of the $.ajax call which looks like });
6. Change that line to }.bind(this)); Your code should now look like this:

63 January, 2023
Kinetic REST Services Guide v.1

$.ajax(settings).done(function (response) {
console.log(response);
        }.bind(this));

7. After the console.log line add a line

this.searchResults = response.value;

This line will take the REST response data in response.value and assign it to the
data.searchResults property. Vue.js will automatically display the results in a table in the UI:

$.ajax(settings).done(function (response) {
console.log(response);
this.searchResults = response.value;
        }.bind(this));

8. Add an additional line to the done method

this.searching = false.

Setting searching = false will simply hide the searching animation now that the search is
complete. Your completed code should now look like this:

$.ajax(settings).done(function (response) {
console.log(response);
//assign the search results
this.searchResults = response.value;
this.searching = false;
        }.bind(this));

9. Save app.js and return to your browser window. Click Refresh to reload the application with your
changes.

10. Type any character into the search input box. This time you should see a searching animation
play and then a table with search results appear showing all customers that start with A.

Wiring the Search Query to the REST Query


You have made great progress, but what the user types is still ignored. The final step to complete our
search application is to add the text the user types into the search box into the REST URL, so it
performs the search they asked for.

1. Leave your browser running and return to Visual Studio Code.


2. Open app.js.

64 January, 2023
Kinetic REST Services Guide v.1

3. Search for var settings = {.The settings object, as discussed earlier, contains the URL that will be
used when we make our REST call. All you need to do is modify the URL to include this.query
which contains the search text the user typed in.
4. Edit the URL replaceing the 'A' in each startswith function with '"+ this.query "'.You need to
include both a single quote ' followed by a double quote " at the beginning and a double quote "
followed by a single quote ' at the end. Your URL should now look like this:

V1: "url":
"https://KineticServer/Kinetic/api/v1/Erp.Bo.CustomerSvc/Customers?%24filter=startswith
(CustID%20%2C'"+ this.query +"')%20or%20startswith(Name%2C%20'"+ this.query
+"')&%24orderby=Name",

5. Return to your browser window and reload the application with your changes.
6. Type in epic into the search input box. This time you should see a searching animation play and
then a table with search results appear showing all customers that have either a CustID or Name
that starts with Epic.

Congratulations!
You've built a fully functional Customer Search Application using Kinetic REST Services.

Now that you have a fully functional application you can see how easy it would be to continue to
modify the REST search that is done. You could easily change out the URL with another rest service or
call multiple rest services to search across multiple objects. You could change this view to a BAQ search,
or an Order search by simply changing out the Service URL and which fields you want to search on. You
can add $select, $orderby, $top, $skip, or other types of $filter options to change the results that are
sent back. Please feel free to try modifying the application further using the REST Services Help to find
any service you want to try.

Calling REST with Azure AD token in C#


In this article, learn how to perform REST calls in C# when Azure AD authentication is implemented.

In the online version of this guide, download the completed sample project code.

Creating a Visual Studio Project


1. Launch Microsoft® Visual Studio®.

2. In the main menu, go to File > New > Project.


3. In the New Project dialog box, verify Visual C# is selected in the tree view.

65 January, 2023
Kinetic REST Services Guide v.1

4. Next, in the Detail panel, select Console Application.


5. For the project Name, enter AbcCodeServiceClientAzureAD.
6. Select the location where you will save the project.
7. Press OK.

Adding NuGet Package


First, add the NuGet package for the Microsoft Authentication Library (MSAL) to the project.

1. In the Solution Explorer, right-click the AbcCodeServiceClientAzureAD project item and select
the Manage NuGet Packages menu item.
2. Press Browse and search for the Microsoft.Identity.Client package.
3. Press Install and step through the wizard.
4. Verify the library is added to your project references.

Adding AzureADAuth Class


Within a project, implement AzureADAuth public class to handle Azure AD token creation and
management.

1. In the Solution Explorer, right-click the AbcCodeServiceClientAzureAD project item.


2. Select the Add > Class menu. The Add New Item dialog box displays. On the List view, the Class
item should be selected by default.
3. Next, in the Name field, enter AzureADAuthREST.

4. Press Add.

66 January, 2023
Kinetic REST Services Guide v.1

5. Adjust the using statements to read the following:

using System;
using System.Linq;
using System.Security;
using System.Threading.Tasks;
using Microsoft.Identity.Client;

6. First, add the following Azure AD settings and adjust them accordingly:

// Settings to be adjusted according to your Azure AD installation

/// <summary>
/// Directory ID - take it from Azure Active Directory properties
/// </summary>
private const string DirectoryID = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
/// <summary>
/// Application ID of the Epicor Web application
/// </summary>
private const string WebAppID = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
/// <summary>
/// Application ID of the Epicor native application
/// </summary>
private const string NativeClientAppID = "XXXXXXXX-XXXX-XXXX-XXXX-
XXXXXXXXXXXX";

// Common settings should be specified like this:

/// <summary>
/// Redirect URL specified for Epicor native application.
/// </summary>
private static readonly string RedirectURL = "https://localhost";
/// <summary>
/// Default scope for Azure AD authentication.
/// </summary>
private static readonly string DefaultScope = "user_impersonation";

67 January, 2023
Kinetic REST Services Guide v.1

For a complete information on the above properties, see either of the below sources:

l Application Help: General > Classic Technical Reference Guides > System
Administration Technical reference Guide > Manage Epicor ERP > Authentication
(User Identity) > Azure AD Multi-Factor Authentication

l Kinetic Installation Guide: Appendices > Azure AD Authentication

7. Add property to hold Client application instance:

private static IPublicClientApplication _clientApp;


/// <summary>
/// Property to store authentication context for the Azure AD tokens
/// </summary>
private static IPublicClientApplication ClientApp
{
get
{
if (_clientApp == null)
{
                    _clientApp = PublicClientApplicationBuilder.Create
(NativeClientAppID)
                        .WithAuthority(AzureCloudInstance.AzurePublic, DirectoryID)
                        .WithRedirectUri(RedirectURL)
                        .Build();
                }
return _clientApp;
            }
        }

8. Add function to get the token. You may use either of the below approaches:

l Show the standard MSAL window to ask for name and password when no valid token
exists:

/// <summary>
/// Show dialog window so user can enter name and password, if necessary
/// </summary>
/// <returns>Access token for the WCF header</returns>

private static async Task<string> InteractiveAzureLogon()


{
var azureAdapp = ClientApp;

// get available Azure AD accounts


var accounts = await azureAdapp.GetAccountsAsync().ConfigureAwait
(false);

// select the first account

68 January, 2023
Kinetic REST Services Guide v.1

var firstAccount = accounts.FirstOrDefault();

// scope should be in the form <WebAppID>/user_impersonation


var scopes = new[] { $"{WebAppID}/{DefaultScope}" };

try
{
// try to get token silently for the selected account
var authResult = await azureAdapp.AcquireTokenSilent(scopes,
firstAccount).ExecuteAsync().ConfigureAwait(false);

return authResult.AccessToken;
            }
catch (MsalUiRequiredException ex)
{
// A MsalUiRequiredException happened on AcquireTokenSilent.
// This indicates you need to call AcquireTokenInteractive to
acquire a token
                System.Diagnostics.Debug.WriteLine($"MsalUiRequiredException:
{ex.Message}");

// show login screen


var authResult = await azureAdapp.AcquireTokenInteractive
(scopes)
                    .WithAccount(accounts.FirstOrDefault())
                    .WithPrompt(Prompt.SelectAccount)
                    .ExecuteAsync().ConfigureAwait(false);

return authResult.AccessToken;
            }
        }

l Specify Azure AD user name and password and obtain a token for the user. This approach
can be used to avoid user interaction:

/// <summary>
/// Get token without user interaction.
/// </summary>
/// <returns>Access token for the WCF header.</returns>
private static async Task<string> AzureLogonForSavedUserAndPassword()
{
// get username and password for Azure AD user from settings.
// Warning: MFA cannot be used and consent should be already
received for this user in the applications,
// Otherwise, the error will be returned:
// AADSTS65001: The user or administrator has not consented to use
the application with ID ...

// Also Allow public client flows should be set to yes, in


Authentication / Advanced settings of the Native Application in Azure AD
// otherwise there will be exception: AADSTS7000218: The request
body must contain the following parameter: 'client_assertion' or 'client_
secret'.

const string userName = "USER@tenant.onmicrosoft.com";

69 January, 2023
Kinetic REST Services Guide v.1

const string password = "Password";

var azureAdapp = ClientApp;

// scope should be in the form <WebAppID>/user_impersonation


var scopes = new[] { $"{WebAppID}/{DefaultScope}" };

var result = await azureAdapp.AcquireTokenByUsernamePassword(scopes,


userName, GetPassword(password))
                .ExecuteAsync().ConfigureAwait(false);

//Return AccessToken, which should be sent to Epicor App Server as


WCF header
return result?.AccessToken;
        }

private static SecureString GetPassword(string password)


{
var securePassword = new SecureString();

if (!string.IsNullOrEmpty(password))
{
foreach (var c in password)
{
                    securePassword.AppendChar(c);
                }
            }
return securePassword;
        }

This approach does not show any user interface, therefore multi-factor
authentication cannot be used. Without administrator consent, the first time
after applications are created, user logon must be done interactively,
because user consent should be received. If this was not done, then the
example above fails with the following error: The user or administrator has
not consented to use the application.

Also, to use this approach, the Allow public client flows setting should be
set to yes in the Authentication/Advanced settings of the Native Application
on the Azure AD portal. Otherwise, you will get an exception -
AADSTS7000218: The request body must contain the following
parameter: 'client_assertion' or 'client_secret'.

9. The following function returns a token to be used in the REST header using one of the
approaches described above:

/// <summary>
/// Gets token for current user

70 January, 2023
Kinetic REST Services Guide v.1

/// </summary>
/// <returns>Access token for the WCF header</returns>
public static string GetToken()
{
if (string.IsNullOrEmpty(NativeClientAppID))
throw new Exception("No settings specified in AzureADAuth");

//This value is used to illustrate how token can be obtained


if (UseInteractiveLogon)
{
return InteractiveAzureLogon().Result;
            }
else
{
return AzureLogonForSavedUserAndPassword().Result;
            }
        }

Adding Token Header to the Server Request


In Program.cs, create a class that will add Authorization header with Azure AD token to every call.

/// <summary>
/// Handler to create authentication header on each server call.
/// </summary>
class AzureADTokenHeaderHandler : WebRequestHandler
{
protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, System.Threading.CancellationToken can-
cellationToken)
{
//Add bearer authorization header on each call.
//It contains valid Azure Active Directory token
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer",
AzureADAuthREST.GetToken());
return base.SendAsync(request, cancellationToken);
        }
    }

71 January, 2023
Kinetic REST Services Guide v.1

Writing Code to Call REST API


1. In the Main function define restUserCallUrl as:

private static string  restUserCallUrl =


"https://KineticServer/Kinetic/api/v1/Ice.BO.UserFileSvc/GetUserFile";

2. Then, create an HttpClient instance, that will use the AzureADTokenHeaderHandler class as a
parameter. After that, you can use this client to make calls with the HttpRequestMessage and
HttpRequestMessage classes.

using (var client = new HttpClient(new AzureADTokenHeaderHandler()))


{
//Create request to make REST call
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post,
restUserCallUrl);

            Console.WriteLine($"Calling POST {restUserCallUrl}");


//Get response
            HttpResponseMessage response = client.SendAsync(request).Result;
    }

Calling REST with Azure AD token in JavaScript


Use the Microsoft Authentication Library for JavaScript (MSAL JS) to handle Azure AD authentication in
your applications. This library works with both plain JS as well as AngularJS applications.

For a complete information on usage of this library, see the following GitHub page:
https://github.com/AzureAD/microsoft-authentication-library-for-js.

In the online version of this guide, download the sample application code for your
reference.

Configuration settings can be set as follows:

l clientId - Application ID of your Web App application. (NativeClientAppID is not used in


JavaScript scenario)
l authority - Directory ID in the following format: "https://login.microsoftonline.com/<Directory
ID>". Specify this setting for single-tenant applications. For multi-tenant applications, use the
tenantId setting instead.

72 January, 2023
Kinetic REST Services Guide v.1

l tenantId - Directory ID of your Azure Active Directory. Use this setting if your application is multi-
tenant.
Here's an official MSAL.JS configuration example from GitHub - https://github.com/AzureAD/microsoft-
authentication-library-for-js/tree/dev/samples/msal-core-samples/VanillaJSTestApp/app/default. And
here are the steps for running the application. We will modify this VanillaJSTestApp to set up MSAL
authentication against a Kinetic application server.

You can install MSAL.JS via:

l npm (npm install msal)


l CDN (Content Delivery Network) by adding this reference in the beginning of the index.html file:

<script type="text/javascript"
src="https://alcdn.msauth.net/lib/1.4.11/js/msal.js"></script>

More info on CDN usage of MSAL.JS here.

1. Load the VanillaJSTestApp files and open them in your editor.

2. Update the authConfig.js file:

l Replace the contents of const msalConfig with code below:

const msalConfig = {
    auth: {
        clientId: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", // WebAppID
// tenantId: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", // Directory ID for
multi-tenant applications
        authority: "https://login.microsoftonline.com/XXXXXXXX-XXXX-XXXX-XXXX-
XXXXXXXXXXXX", //Directory ID for single-tenant applications
        redirectUri: window.location, // here, redirect URL is equal to the
current page URL. Redirect URL should be registered in the Azure AD application.

l Specify clientId, tenantId or authority (depending on whether your app is single- or


multi-tenant), and redirectUri. ClientID is Web Application ID registered for Kinetic. The
redirectUri should match the URI specified in the Azure AD web application settings
(Authentication >Redirect URIs - for example, https://localhost/CoreJsAzureAD).

l Now add a new kineticLoginRequest object. Define the scope in the following format:
<WebAppID>/user_impersonation:

73 January, 2023
Kinetic REST Services Guide v.1

// Add scope to connect to a <span class="Variables.Product mc-


variable">Kinetic</span> app server
const kineticLoginRequest = {
    scopes: [msalConfig.auth.clientId + "/user_impersonation"],
    forceRefresh: false // Set this to "true" to skip a cached token and go to
the server to get a new token
};

This scope will be sent to Azure AD to get the token for Kinetic.

l Declare one more constant - kineticConfig - and specify the appServerUrl to use for REST
calls to Kinetic:

// Url of <span class="Variables.Product mc-variable">Kinetic</span> app server


- Replace "KineticServer" with the actual server URL
const kineticConfig = {
    appServerUrl: "https://KineticServer"
};

3. Update index.html to trigger a REST call to Kinetic:

l In index.html, find the closing tag for the Read Mails button and add another button
below it to test a Kinetic call:

<button class="btn btn-primary" id="callKinetic" onclick="callKinetic()">Call


Kinetic</button>

l Add reference to a new script at the end of the file, before the closing </body> tag:

<script type="text/javascript" src="./kineticCall.js"></script></body>

In the next step you will create the kineticCall.js that will contain a function performing the
call.

4. Create a new file - kineticCall.js and add the following function to it:

V1:

function callKinetic() {
if (myMSALObj.getAccount()) {
        getTokenPopup(kineticLoginRequest).then(response => {

const headers = new Headers();

74 January, 2023
Kinetic REST Services Guide v.1

const bearer = `Bearer ${response.accessToken}`;


            headers.append("Authorization", bearer);

// Additionally, for REST API v.2


//headers.append("x-api-key",
"atI7eSN1f1Uuao8gsgtDeWzRv4LiC9OotpUbzFTAPN7mk"); //replace API Key with the actual
value

const options = {
                method: "POST",
                headers: headers
            };

console.log('request made to Kinetic App server at: ' + new Date


().toString());

//For REST API v.1


const endpoint = kineticConfig.appServerUrl +
"/api/v1/Ice.BO.UserFileSvc/GetUserFile";

//For REST API v.2 - Replace the EPIC06 company with a relevant value if
necessary
//const endpoint = kineticConfig.appServerUrl +
"/api/v2/odata/EPIC06/Ice.BO.UserFileSvc/GetUserFile";

            fetch(endpoint, options)
                .then(response => response.json())
                .then(response => {
console.log(response);
const userID = response.returnObj.UserFile[0].UserID;
const externalIdentity = response.returnObj.UserFile
[0].ExternalIdentity;
                    alert("Welcome user " + userID + ", external identity: " +
externalIdentity);
                })
                .catch(error => console.log(error));

        }).catch(error => {
console.log(error);
        });
    }
}

The call checks for a valid Azure AD token, then creates an Authorization header with the Bearer
token value.

Then the POST request to <...>/Ice.BO.UserFileSvc/GetUserFile is made to get information on


currently logged in Kinetic user in an alert message box.

To test this call, make sure you have defined:

75 January, 2023
Kinetic REST Services Guide v.1

l Azure AD settings in Azure Active Directory Configuration Maintenance


l External identity for the Kinetic user.  

Calling BPM Auto Print, MRP, or Multi-Company Processes


In order to launch MRP, Multi-Company logic, or BPM Auto-Printing via REST calls, an AppServer URL
pointing to a Windows authentication binding or Kinetic user name/password binding must be
specified on the System Agent Maintenance > Detail tab.

Note this value cannot be set to Azure AD authentication binding.

76 January, 2023
Kinetic REST Services Guide v.1

Troubleshooting and Security


Understanding REST API Exceptions
This article explains correlation of service exceptions with HTTP error codes returned by the Kinetic
REST API. Depending on the format defined in the Accept request header, the Kinetic REST API returns
error details in either JSON or XML format:

Accept Header Value Response Format

Empty, */*, or application/json JSON


All other XML

Here's an example of an XML response:

<?xml version="1.0" encoding="utf-8"?>


<ApiExceptionResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="h-
ttp://www.w3.org/2001/XMLSchema-instance">
<HttpStatus>BadRequest</HttpStatus>
<ReasonPhrase>REST Api Exception</ReasonPhrase>
<ErrorMessage>Incorrect service name. Example: Ice.BO.TipSvc</ErrorMessage>
<ErrorType>Epicor.RESTApi.ErrorHandling.ApiException</ErrorType>
</ApiExceptionResponse>

This is an example of a JSON response:

{
"HttpStatus": 404,
"ReasonPhrase": "REST Api Exception",
"ErrorMessage": "OData path is undefined for the request https://Kinet-
icServer/Kinetic/api/v2/odata/EPIC06/Ice.Bo.TipSvc/Tips1/",
"ErrorType": "Epicor.RESTApi.ErrorHandling.ApiException"
}

Mapping Between Kinetic Service Exceptions and HTTP Error Codes


This section includes the list of the most common Kinetic service exceptions.

UnauthorizedAccessException
HTTP Error Code: 403 - Forbidden

What's wrong?

77 January, 2023
Kinetic REST Services Guide v.1

Access to method is disabled - for example:

https://KineticServer/Kinetic/api/v2/odata/EPIC03/Ice.BO.TipSvc/Tips
{
    "HttpStatus": 403,
    "ReasonPhrase": "REST Api Exception",
    "ErrorMessage": "Access denied (BO.Tip).",
    "ErrorType": "System.UnauthorizedAccessException"
}

Microsoft.Data.OData. ODataException
HTTP Error Code: 400 - Bad request

What's wrong?

OData cannot process received query - for example:

https://KineticServer/Kinetic/api/v2/odate/EPIC03/Ice.BO.TipSvc/Tips?$filter=TipNum eq abc

<?xml version="1.0" encoding="utf-8"?>


<ApiExceptionResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="h-
ttp://www.w3.org/2001/XMLSchema-instance">
<HttpStatus>BadRequest</HttpStatus>
<ReasonPhrase>REST Api Exception</ReasonPhrase>
<ErrorMessage>Could not find a property named 'abc' on type 'Ice.Tip'.</ErrorMessage>
<ErrorType>Microsoft.Data.OData.ODataException</ErrorType>
</ApiExceptionResponse>

Ice.Common.RecordNotFoundException
HTTP Error Code: 403 - Forbidden

What's wrong?

Requested item is not found - for example:

https://KineticServer/Kinetic/api/v2/odata/EPIC03/Ice.BO.TipSvc/Tips('EPIC03','EP',0)

{
    "HttpStatus": 404,
    "ReasonPhrase": "REST Api Exception",
    "ErrorMessage": "Record not found.",
    "ErrorType": "Ice.Common.RecordNotFoundException",
    "ErrorDetails": [
{
            "Message": "Record not found.",
            "Type": "Error",

78 January, 2023
Kinetic REST Services Guide v.1

            "Table": "Tip",
            "Program": "Epicor.Ice.dll",
            "Method": "InnerGetByID",
            "ColumnNumber": 17,
            "LineNumber": 705
        }
    ]
}

DuplicateRecordException
HTTP Error Code: 409 - Conflict

What's wrong? There is a duplicate record shown on the client.

Ice.Common.BusinessObjectException
(and derived, like BLException)

HTTP Error Code: 400 - Bad request

What's wrong? There is an error in business logic.

Ice.Common.InvalidSessionException
HTTP Error Code: 410 Gone

What's wrong?

SessionID used in the custom SessioInfo header not found in cache - for example:

POST https://KineticServer/Kinetic/api/v2/odata/EPIC03/Ice.Lib.SessionModSvc/Logout
Header SessionInfo: {"SessionID": "824471b8-5003-4178-af90-dd7aea357499"}    
{
    "HttpStatus": 410,
    "ReasonPhrase": "REST Api Exception",
    "ErrorMessage": "Session with SessionID = 824471b8-5003-4178-af90-dd7aea357499 is
invalid. Session has either timed out or has been deleted. You must login again to con-
tinue.",
    "ErrorType": "Ice.Common.InvalidSessionException”
}

ConversionsPendingException
HTTP Error Code: 503 - Server is unavailable

What's wrong? A conversion is pending. This error displays on the client.

79 January, 2023
Kinetic REST Services Guide v.1

DBMismatchException
HTTP Error Code: 503 - Server is unavailable

What's wrong? A conversion is pending. This error does not display on the client.

EpicorTemplateExceptionBase
(and derived)

HTTP Error Code: 503 - Server is unavailable

What's wrong? An error occurred during processing. Exception will be visible on the client if it is marked
as Visible in the application code:

EpicorTemplateExceptionBase.Classification == ExceptionClassification.Public

REST API BAQ Service Errors


HTTP Error Code: 400 - Bad request

What's wrong? Errors returned during BAQ and UBAQ execution. The contents of returned Errors table
are loaded into BusinessObjectException and return to the client as part of BusinessObjectException.
For example:

{
  "HttpStatus": 400,
  "ReasonPhrase": "REST Api Exception",
  "ErrorMessage": "UBAQ execution failed with error: \r\nPart is required.\r\nPart Descrip-
tion is required.",
  "ErrorType": "Ice.Common.BusinessObjectException",
  "ErrorDetails": [
{
      "Message": "UBAQ execution failed with error: ",
      "Type": "Error",
      "Program": "Epicor.RESTApi.dll",
      "Method": "ThrowBaqRESTApiException",
      "ColumnNumber": 13,
      "LineNumber": 304
    },
{
      "Message": "Part is required.\r\nPart Description is required.",
      "Type": "Error",
      "Table": "OrderDtl",
      "Program": "Epicor.RESTApi.dll",
      "Method": "ThrowBaqRESTApiException",
      "ColumnNumber": 17,
      "LineNumber": 316,
      "RowID": "3125094a-908b-4266-9cf9-405d211dd54a"

80 January, 2023
Kinetic REST Services Guide v.1

    }
  ]
}

OData POST/PATCH/DELETE Errors


(related to UpdateExt execution)

HTTP Error Code: 400 - Bad request

What's wrong? Errors in UpdateExt execution during CUD operations in OData.

The contents of returned BOUpdErrorTableset dataset are loaded into BusinessObjectException and
return to the client as part of BusinessObjectException.

Each row in the BOUpdErrorTableset is returned as ErrorDetail. For example:

{
    "HttpStatus": 400,
    "ReasonPhrase": "REST Api Exception",
    "ErrorMessage": "Part is required.\r\nPart Description is required.",
    "ErrorType": "Ice.Common.BusinessObjectException",
    "ErrorDetails": [
{
            "Message": "Part is required.\r\nPart Description is required.",
            "Type": "Error",
            "Table": "OrderDtl",
            "Program": "Epicor.RESTApi.dll",
            "Method": "ThrowUpdateExtRESTApiException",
            "ColumnNumber": 17,
            "LineNumber": 181
          }
    ]
}

All Other Exceptions


HTTP Error Code: 500 - Internal server error

These errors do not display on the client

Handling Errors
The Web.API uses the <system.web><customErrors> mode to control how errors display in client
installations. This mode value is case sensitive. If you do not specify a value, the system uses the
<customErrors mode="RemoteOnly" /> setting. Through this setting, the local users see all error

81 January, 2023
Kinetic REST Services Guide v.1

information while the remote users see a brief, generic message that states they should contact their
system administrator.

If you want to display the brief, generic error message for both remote users and client users, set the
option to this value:

<system.web>    
     <customErrors mode="On" />
</system.web>

However, if you wish to display the complete ASP.NET error message to both remote users and client
users, set the option to this value:

<system.web>
     <customErrors mode="Off" />
</system.web>

The customErrors setting of the web.config file hides only the server errors that are not
supposed to be shown on the client. By default, these are errors with the HTTP code of
50x.

Errors returned from the server to the client contain more detail now. The main properties are the same
as before, but the ErrorDetails contains a list of details similar to the Kinetic Business Object
exceptions.

To learn more about how to use the customErrors setting, review the following
Microsoft resource: https://msdn.microsoft.com/en-us/library/h0hfz6fc(v=vs.100).aspx

Setting Up Data Security


You secure the data that comes from REST by implementing authentication codes.

Token Authentication is configured automatically during application server deployment. If


you have issues with automatic configuration and need to run the process manually, refer
to Administration Console help (Kinetic Application Server - <version> > Configure Token
Authentication > Activate Tokens).

82 January, 2023
Kinetic REST Services Guide v.1

This article describes the code you enter to secure the data you display through REST services. You then
secure the streaming data from malicious activity.

You should always use the HTTPS protocols with REST services. These protocols are a secure way for
REST to transfer data between Kinetic and your third party application. REST supports two
authentication methods:

l Basic Authentication – The User Name and Password are combined into a string, separated by a
colon, and encoded by using Base64. The resulting data is placed in an Authorization header. It
uses both Authorization: Basic and an encoded string.
l Token Authentication – You first get the bearer token for the user from the token service. Then
send this access token in the Authentication header using this format: Authorization: Bearer
(token string).

Basic Authentication
This Basic Authentication code example specifies the user name and password in the request header.
You can also add optional request settings to specify the Company and Plant.

static HttpClient CreateClient()    


{    
            HttpClient client = new HttpClient();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue


("Basic", Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "man-
ager", "Epicor123"))));

//header to set current company


            ICallHeader hdr = new CallSettings("EPIC06", "MfgSys", "", "");
            client.DefaultRequestHeaders.Add(hdr.Name, JsonConvert.SerializeObject(hdr));

return client;
        }

To use this authentication code:

V1:

HttpClient client = CreateClient();


HttpResponseMessage response = client.GetAsync(ServiceUrl + "/Ice.Bo.Pro-
cessTaskSvc/ProcessTasks").Result;  

Token Authentication
This Token Authentication code example gets the token from the token resource.

83 January, 2023
Kinetic REST Services Guide v.1

V1:

private static string ObtainToken()


{
            HttpClient client = new HttpClient();
// Add an Accept header for JSON format.
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue
("application/json"));
try
{
const string TokenCreateURL = "https://Kinet-
icServer/Kinetic/TokenResource.svc/";
var request = new HttpRequestMessage()
{
                    RequestUri = new Uri(TokenCreateURL),
                    Method = HttpMethod.Post,
                };
//send user credential
                request.Headers.Add("username", "manager");
                request.Headers.Add("password", "Epicor123");

// Get response
                HttpResponseMessage response = client.SendAsync(request).Result;

if (response.IsSuccessStatusCode)
{
//Parse the response body.
var tokenObj = response.Content.ReadAsAsync<TokenObject>().Result;
//Get access token value
return tokenObj.AccessToken;
                }
else
{
                    Console.WriteLine("{0} ({1})", (int) response.StatusCode,
response.ReasonPhrase);
                }

            }
catch (AggregateException ex)
{
                Console.WriteLine(ex.Message);

            }
return null;
        }

You can now use this token to authenticate calls:

V1:

//get token from token resource


var accessToken = ObtainToken();

if (!string.IsNullOrEmpty(accessToken))

84 January, 2023
Kinetic REST Services Guide v.1

{
                HttpClient  getTipCall = new HttpClient();
//put token into Authentication header
                getTipCall.DefaultRequestHeaders.Authorization = new Authentic-
ationHeaderValue("Bearer", accessToken);

string tipUrl = "https://Kinet-


icServer/Kinetic/Server/Ice/BO/Ice.Bo.TipsSvc/Tips";

                HttpResponseMessage response = getTipCall.GetAsync(tipUrl).Result;

if (response.IsSuccessStatusCode)
{
var tipObj = response.Content.ReadAsAsync<JObject>().Result;

foreach (var p in tipObj)


{
                        Console.WriteLine("{0} ({1})", p.Key, p.Value);
                    }

                }
else
{
                    Console.WriteLine("{0} ({1})", (int)response.StatusCode,
response.ReasonPhrase);
                }

            }

Single Sign-On
To keep the REST transfer secure while making it easier for users to access the data, implement the
Single Sign-On feature.

You do this by activating Windows Authentication within your system. To activate Windows
Authentication:

1. Access your server machine.


2. Launch Internet Information Services (IIS) Manager.
3. Now for the virtual folder, activate the Authentication folder.
4. Enable Windows Authentication.
This user can now connect to REST services without entering credentials. The system uses the header to
verify the account is secure and permitted to access the service.

l If you are on product version prior to 10.2.300, note that when you use Windows Authentication
in the Internet Information Services (IIS) Manager, the TokenResource.svc and other resources
that use webHttpBinding (Web.svc, ECC.svc, and so on) cannot start. If you need both token

85 January, 2023
Kinetic REST Services Guide v.1

authentication and Windows Authentication to work on the application server, change the
webHttpBinding definition in the web.config file. Change the <transport clientCredentialType>
setting to use Windows; by default, this setting is set to None:

<webHttpBinding>
        <binding name="RestHttps" transferMode="Buffered">
          <security mode="Transport">
            <transport clientCredentialType="Windows" />
          </security>
          <readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxDepth="2147483647" maxStringContentLength="2147483647" />
        </binding>
      </webHttpBinding>

For product version 10.2.300 and later, no manual action is needed; the <transport
clientCredentialType> is set to InheritedFromHost by default:

<webHttpBinding>
        <binding name="RestHttps" transferMode="Buffered">
          <security mode="Transport">
            <transport clientCredentialType="InheritedFromHost" />
          </security>
          <readerQuotas maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxDepth="2147483647" maxStringContentLength="2147483647" />
        </binding>
      </webHttpBinding>

Azure Active Directory Token Authentication


Azure Active Directory token should be sent to Kinetic REST API the same way as internal Kinetic token
by adding Authorization header and setting its value to Bearer <Access token value>.

Here's how you can retrieve an Azure AD authentication token:

86 January, 2023
Kinetic REST Services Guide v.1

1. Create an IPublicClientApplication instance:

private static IPublicClientApplication _clientApp;


/// <summary>
/// Property to store authentication context for the Azure AD tokens
/// </summary>
private static IPublicClientApplication ClientApp
{
get
{
if (_clientApp == null)
{
                    _clientApp = PublicClientApplicationBuilder.Create
(NativeClientAppID)
                        .WithAuthority(AzureCloudInstance.AzurePublic, DirectoryID)
                        .WithRedirectUri(RedirectURL)
                        .Build();
                }
return _clientApp;
            }
        }

2. Use the IPublicClientApplication instance to get token using one of the following methods:

87 January, 2023
Kinetic REST Services Guide v.1

l Show a standard MSAL window to ask for name and password when no valid token exists:

private static async Task<string> InteractiveAzureLogon()


{
var azureAdapp = ClientApp;

// get available Azure AD accounts


var accounts = await azureAdapp.GetAccountsAsync().ConfigureAwait
(false);
// select the first account
var firstAccount = accounts.FirstOrDefault();

// scope should be in the form <WebAppID>/user_impersonation


var scopes = new[] { $"{WebAppID}/{DefaultScope}" };

try
{
// try to get token silently for the selected account
var authResult = await azureAdapp.AcquireTokenSilent(scopes,
firstAccount).ExecuteAsync().ConfigureAwait(false);

return authResult.AccessToken;
            }
catch (MsalUiRequiredException ex)
{
// A MsalUiRequiredException happened on AcquireTokenSilent.
// This indicates you need to call AcquireTokenInteractive to
acquire a token
                System.Diagnostics.Debug.WriteLine($"MsalUiRequiredException:
{ex.Message}");

// show login screen


var authResult = await azureAdapp.AcquireTokenInteractive
(scopes)
                    .WithAccount(accounts.FirstOrDefault())
                    .WithPrompt(Prompt.SelectAccount)
                    .ExecuteAsync().ConfigureAwait(false);

return authResult.AccessToken;
            }
}

l Specify Azure AD user name and password and obtain a token for the user. This approach
can be used to avoid user interaction:

private static async Task<string> AzureLogonForSavedUserAndPassword()


{
// Get username and password for Azure AD user from settings.
// Warning: MFA cannot be used and consent should be already
received for this user in the applications,
// Otherwise the error will be returned:
// AADSTS65001: The user or administrator has not consented to use
the application with ID ...

88 January, 2023
Kinetic REST Services Guide v.1

// Also Allow public client flows should be set to yes, in


Authentication / Advanced settings of the Native Application in Azure AD
// otherwise there will be exception: AADSTS7000218: The request
body must contain the following parameter: 'client_assertion' or 'client_
secret'.

const string userName = "USER@tenant.onmicrosoft.com";


const string password = "Password";

var azureAdapp = ClientApp;

// scope should be in the form <WebAppID>/user_impersonation


var scopes = new[] { $"{WebAppID}/{DefaultScope}" };

var result = await azureAdapp.AcquireTokenByUsernamePassword(scopes,


userName, GetPassword(password))
                .ExecuteAsync().ConfigureAwait(false);

//Return AccessToken, which should be sent to Epicor App Server as


WCF header
return result?.AccessToken;
        }

private static SecureString GetPassword(string password)


{
var securePassword = new SecureString();

if (!string.IsNullOrEmpty(password))
{
foreach (var c in password)
{
                    securePassword.AppendChar(c);
                }
            }
return securePassword;
   }

CORS Support
Through Cross-Origin Resource Sharing (CORS), restricted web resources from one domain can be
requested from another outside domain.

By default, cross-domain requests are not allowed because they can perform POST, PUT, DELETE, and
other advanced HTTP requests which should be restricted to authorized clients only.

However, through the CORS restriction configuration, you can authorize any hosts, or specific trusted
hosts, to access the REST services. For example, if you create a web application that uses the REST
services hosted on its own server, you need to enable a CORS exception for that server to access the
services.

89 January, 2023
Kinetic REST Services Guide v.1

Starting from product version 10.2.300, access to any host is enabled by default. However,
you can choose to enable access to only a limited set of hosts that need access to the
service.

Currently only limited CORS functionality is available in Kinetic. You can set up the web.config to use
the CorsOrigins application settings to specify the origin of the requests. Available host options:

l Enable access to any host

l Define a specific host

l Define a comma-delimited list of hosts

Examples:

l <add key="CorsOrigins" value="*" /> - default option, CORS allows access to all sites.

l <add key="CorsOrigins" value="https://localhost" /> - CORS only allows requests from only
https://localhost .

l <add key="CorsOrigins" value="https://localhost, https://localhost" /> - CORS only allows


access from https://localhost and https://localhost .

90 January, 2023

You might also like