Custom REST API Service Using Logics

Logics can be used to create a custom HTTP API between Pricefx and other systems. This is a very powerful feature which opens a lot of possibilities, however it should be used only if the standard APIs are not good enough. The typical business case is to provide an interface to e-commerce applications which query Pricefx to find out the price from the base price list with the discount applied from the contract manager. Note that in such a case, the logic must perform very well to quickly serve the request and therefore the number of items being queried is usually limited, e.g., to 50 or 100, which is usually acceptable limitation since the e-commerce platforms use paging mechanism anyway.

Only a logic of generic type (formulaNature is not defined) can be used as an API endpoint.

 

HTTP Endpoint

Each custom API is implemented using a logic of generic type (formulaNature not specified) and the APIs are called using the following HTTPS endpoint:

https://<HOSTNAME>.pricefx.com/pricefx/<PARTITION>/formulamanager.executeformula/<LOGIC_NAME>/?output=rawjson

where placeholders <HOSTNAME>, <PARTITION>, <LOGIC_NAME> represent the real hostname (e.g., www), partition name and logic name.

The query string ?output=rawjson is not mandatory, but it is commonly used since it removes the standard “data” envelope from JSON and provides the result in a condensed and commonly expected format.

Alternatively, you can also use the formulamanager.executeformulaservice API, which allows to values caching using api.global between the calls, see REST API documentation .

Inputs and Outputs

HTTP API is defined by a request in the JSON format, which contains the “data” section which contains the input fields:

{ "data": { "input1" : ..., "input2" : ..., "input3" : ..., .... } }

Each input field of the request is implemented by an input parameter of the logic (its name and value).

 

The response is also in the JSON format, which in case of ?output=rawjson contains the following structure of output fields:

{ "output1" : ..., "output2" : ..., "output3" : ..., .... }

Each output field is represented by a logic element (its name and value) which has to have the field “Display” set to “Integration” (or alternatively “Everywhere”).

This fact about inputs and outputs allows you to create API of almost any request and response structure.

 

If the ?output=rawjson parameter is omitted, the response is in the full format where the “data” field contains a list of elements in the full format (FormulaElementResult object, includes e.g., label, format etc.):

{ "node" : "user1", "csrfToken" : ..., "data" : [ { "resultName" : ..., "resultLabel" : ..., "result" : ..., "excludeFromExport" ..., "warnings" : ..., "alertMessage" : ..., "alertType" : ..., "displayOptions" : ..., "formatType" : ..., "suffix" : ..., "resultType" : ..., "cssProperties" : ..., "userGroup" : ..., "resultGroup" : ..., "overrideValueOptions" : ..., "overrideAllowEmpty" : ..., "labelTranslations" : ..., "overridable" : ..., "overridden" : ..., "resultDescription" : ..., }, { .... } ], "status" : 0 }

Example: GetPrice API

In this example, you will learn how to create a very simple API that returns a price for a given list of SKUs from a price grid of a given name.

Expected request:

Expected response – approved prices from the LPG:

We suppose a limit of SKUs in each API call to be 100 at maximum.

1. Create Logic

Create a logic of generic type (no formulaNature selected) and give it a name, e.g., “GetPrice” and implement the following elements:

PriceGridName, with “Display mode” set to “never”:

 

Skus, with “Display mode” set to “never”:

For the development purposes and smooth testing in Studio you can define the skus parameter as api.jsonDecodeList(api.stringUserEntry("skus")). But for the real use, it is better to use a List input value instead of a String.

 

AbortInputGeneration, with “Display mode” set to “never”:

isInputGenerationExecution is supported from version 10.0. In older versions use isSyntaxCheck.

PriceGridId, with “Display mode” set to “never”:

 

IsError, with “Display mode” set to “never”:

 

Result, with “Display mode” set to “Integration”:

 

Error, with “Display mode” set to “Integration” and “Condition” set to “IsError”:

Naming conventions of the element names:

  • Integration elements – camelCase (with lower-case initial letter); to have the lower-case letter in JSON.

  • Other elements – CamelCase (with upper-case initial letter).

2. Generate Parameters

Go to the Parameters tab and define the input values:

priceGridId = “Base Pricelist”

If you set the skus parameter as api.jsonDecodeList(api.stringUserEntry("skus")), you set the sku parameter to ["MB-0001", "MB-0002"]. Otherwise, since you cannot enter a List value into a field, skip entering the “skus” parameter value for now.

Save the parameter preset for later use.

3. Call API Endpoint

Navigate to the “API” tab of the logic editor in Studio. The endpoint sits on the server, therefore select “Deploy logic” and click the green run button. The logic will get deployed and executed and then the “Renspose body” tab will show the response.

If you have set the skus parameter as api.stringUserEntry("skus"), switch to the “Request payload” tab, deselect “Payload from Parameters” and assign the “skus” field a List value of the skus to be queried:

Click the green run button and you will get a response such as:

If you call the API, e.g., with a non-existing LPG value in the priceGridName parameter, you will receive the following error response:

For the debugging purposes, if you are not using a Map or List in input values, you can also utilize the test execution of the logic by clicking the Test logic button.

Security

The user account that is used for calling the API requires PRICINGFORMULA_EXECUTE permission which is included in several user roles (the ones that may need configurator logic). If the integration account should have the minimalistic access, the View Products role is the candidate.

 

See also: https://pricefx.atlassian.net/wiki/spaces/KB/pages/3252093005

Found an issue in documentation? Write to us.