Skip to content

About this document, TITLE

The purpose of this document is to describe the architecture of Key2print editor and allow its integration to the third party systems.

Document history

Version Date Version description
1.0 30.04.2020 First version of this document
1.1 05.06.2020 • Added placeholder functionality
• Added starting user worksession with fixed project template
• Added editor setup to user worksession
• Minor fixes
1.2 15.06.2020 • Changed editor setup format and added additional options
1.3 17.06.2020 • Added size parameters to wrapper
• Added additional worksession start examples
1.4 25.06.2020 • Added project list to WEBAPI
• Added editorSetup colors
• Minor example fixes
1.5 03.07.2020 • Added project “description” field
• Added project thumbnail on project list inside of template format

Definitions

CustomerHost application end-user. Usually represented by the real-world customer.

Editor – service which allows third-party applications to embed WYSIWYG editor on their web page. It consists of frontend, backend, and API.

Editor API/WEBAPI – WEBAPI of the editor, which allows its configuration and obtaining session keys necessary for embedding editor frontend.

Editor backend – server side application which stores service data and hosts editor WEBAPI.

Editor frontend – client side application which runs in iframe embedded on third party application.

Editor wrapper – JavaScript library that encapsulates the process of embedding editor iframe.

Host application – third party application (usually an e-commerce platform) which integrates Editor for its functionality. It talks to Editor API and embeds Editor frontend iframe.

Merchant – actor of Editor which represents host application instance. Each host application (e-commerce shop) has a unique merchant credentials to interact with the editor (either via Editor API or Editor Wrapper).

Order item – entity representing product ordered on the host application.

Placeholder – entity representing field that could be inserted into the project template to be automatically filled with user’s data passed to a user work session.

Product – product that is selled by host application. Usually it is the thing that needs custom design per order item, made by customer, using the Editor.

Product gateway – part of editor that allows the product to be dynamically configured inside of Editor iframe. In order to use it, host application has to implement callback API.

Product setup – set of product option values that allow to order it from host application.

Project – design made by user, using the editor.

Project template - design made by the merchant, using the editor. Its purpose is to act as a starting template for users, who then make their own projects.

Template format – category for project templates. Template formats could be mapped to product setups, using the product gateway.

User – Actor of Editor which represents customer of Host application. User works on Editor frontend running in Iframe on Host application.

Work session – generated via Editor API, unique access permission required to authenticate Editor frontend upon opening of Iframe. Each work session contains unique access token and options set which defines how Editor should behave.

General system description

Key2Print Editor is web service that allows third-party companies to integrate WYSIWYG editor into their applications. Its main goal is to provide an easy and platform agnostic way to embed editor in applications capable to use web browser. All complex operations, like processing lengthy binary data or preparing run time environment is maintained on the Key2print side, so even limited applications (like eCommerce plugins) could fully utilize its capabilities.

Although Key2Print Editor is meant to be used as a designing tool for other applications, it is a completely standalone application itself. Beside written in JavaScript front it also has its own backend and tools that ease its embedding.

Whole system consists of four main elements :

Editor backend

This is the main service server, which stores all required data and communicates with the outside world. It also does any heavy lifting involving file uploads, binary data processing, and generation of output documents

Editor frontend

This is written in javascript application that runs in Iframe embedded on the third-party host application. This is the place, where all the WYSIWYG operation takes place.

Editor Wrapper

Editor Wrapper is a small Javascript library that opens editor iframe and enables some basic communication between running editor and embedding application (for example, the editor can inform that user has ended his work). It is written in pure Javascript to prevent any possible conflicts with already existing software.

Editor WEBAPI

Editor WEBAPI is used to programmatically configure editor resources (for example to manage user/customer lists) and to start work sessions making operation context of Editor frontend running in iframe. Key2print editor WEBAPI is served from Editor backend.

Editor actors

Editor system has two main actors:

Merchant

This actor represents backend interactions between the host application and the Editor. Both WEBAPI calls and results made by using merchant work sessions (see merchant work sessions) are considered as made by this actor.

The life of this actor begins as Editor WEBAPI credentials are generated for the host application.

User

This actor represents the end-user (customer) of the host application. He made his own projects basing on project templates.

The life of this actor begins as the host application creates new user using the Editor WEBAPI.

Entity structure

Basic system entities and their relationships are as shown on this simplified ERD diagram.

[DIAGRAM IMAGE HERE]

Work Sessions

Work sessions are entities that represent opened editor Iframes. Each work session has to be started by WEBAPI and then passed to editor wrapper in order to open a properly configured editor frontend. Upon starting of the work session, the host application receives its security token (this is what editor wrapper expects) and its expiration date (usually 1 hour from the WEBAPI call). After this date, the editor wrapper will no longer be able to open the editor iframe. Although session token could be stored and reused (or sent to be reused), it is recommended that each case of editor iframe use their own unique session

The WEBAPI work session starting method is described here

There are two types (modes) of work sessions. First one dedicated for merchants (merchant mode) and the second one for users (user mode).

Merchant Work Sessions

Merchant work session mode is used by host application to create template content to be later used by users.

Usually, this type of work session is used in the backend of the host application, where the system administrators can set up template formats and create project templates.

User Work Sessions

User work session mode is used by the host application to enable its customer to design projects for their order items.

Each user work session is started for one, already existing user (it cannot work without the user context). There is also a possibility to start the session for previously-stored projectId as long as it was made for selected user context (its meant to be used as an edit of existing user project). When project Id was not defined, the Editor frontend will open with a blank new project.

The user work sessions could also be started with a new project filled with contents copied from the defined project template. In this case projectTemplateId parameter should be supplied.

Work Session Product Gateway

User work sessions could also be configured to work with the optional Product Gateway. Configuration of Product Gateway is passed upon the starting of the work session and affects only this one work session.

Product Gateway does not work with merchant work sessions.

For more information see Product Gateway paragraph and starting the work session api method.

Placeholders

Placeholders are special fields that could be inserted into the project template to be later populated with data passed to the user work session. Although they are managed by merchants directly from the editor window, management thorough WEBAPI is also possible.

Placeholder types

Currently, there is only one type of placeholder, which is “text”. It represents a simple text field that will be populated by a string passed to user work session.

A list of available types will be extended in the future.

Placeholder values

Inserted to the user work session placeholder data has a form of JSON object defined by pseudocode as below:

"placeholderValues":{
    "placeholderSystemName": {
        "placeholderParameterName": “placeholderParameterContent”
    }
}

Example 1

"placeholderValues":{
    "company_name": {
        "value": "Key2print"
    }
}

Text placeholder

Parameter name Parameter content
Value String value to be inserted into placeholder

Use case scenarios

General Key2print Editor architecture is designed to be very elastic, so it can fit many systems and solutions. Some operations could be performed in more than one way and not all functionalities had to be used.

Here, we present some common use case scenarios which could serve as some examples of how real-life integration could be done.

For a better scenario clarity, we assume that our sample host application implements a widely acknowledged Model-View-Controller (MVC) design pattern.

Opening merchant editor iframe

Before any user could create their own project, administrator of the host application have to prepare proper project templates and their categories (template formats). In order to handle this task, the backend of the host application should implement a sub page (action of a controller) that opens editor in merchant mode (see merchant work sessions). It is assumed that access to this page would be fully controlled by credentials on the host application side (for example only host application administrators could access it).

Steps for performing this scenario may look like this :

1. Start merchant work session

On the server-side (in the action of the controller), the host application should use WEBAPI and call the work session start method and request a merchant mode work session. Received session token should be then passed to the rendering of the view.

Work Session : see Work Sessions Access to WEBAPI : see API credentials WEBAPI authentication : see WEBAPI Post request Starting Work Sesion : see Work session – start new editor session

2. Open editor with editor wrapper

After obtaining work session token, host application can now render the view using the editor wrapper. In order to do so, view should include editor wrapper library, create proper editor container and run wrapper code (passing obtained session token to it). Editor will then embed its iframe into that container.

Editor Wrapper : see Editor Wrapper

Opening user editor iframe

This scenario assumes that the editor is opened for the host application customer so he can create a project for the ordered product. For example, it could be the design of own business card that would be ordered via host application.

Steps for performing this scenario may look like this :

1. Editor user creation

All user work sessions have to work in context of a single, selected user that has to be created using the WEBAPI. This limitation prevents users from seeing content made by other users.

In general usage scenarios, the host application has its own customer entity. Before any of the customers could access the editor, the host system has to create individual user records for them thorough the WEB API. We recommend to generate userId upon first customer editor usage and then store it in customer record for future usage.

When host application does not implement customer entity (for example it provides service to anonymous users) it could store userId in session, or even generate new userId for each editor usage, but re usage of user-created content maybe then not possible.

Work Session : see Work Sessions Access to WEBAPI : see API credentials WEBAPI authentication : see WEBAPI Post request Adding user : see Users – add user

2. Start user work session

When user is already created and host application has its userId, work session could be started. On the server-side (usually in the product configuration action of the controller), the host application should use WEBAPI and call the work session start method and request a user mode work session (passing the user obtained in a previous step). Received session token should be then passed to the rendering of the view.

Work Session : see Work Sessions Access to WEBAPI : see API credentials WEBAPI authentication : see WEBAPI Post request Starting Work Session : see Work session – start new editor session

3. Open editor with editor wrapper

After obtaining work session token, host application can now render the viewusing the editor wrapper. In order to do so, view should include editor wrapper library, create proper editor container and run wrapper code (passing obtained session token to it). Editor will then embed its iframe into that container.

It is assumed that the host application has already implemented the underlying JavaScript application that is used for product configuration. Editor wrapper code is a single class written in pure JavaScript that could be easily integrated with any tech-stack. The editor will open its iframe directly after the instantiation of this class and then calling method open().

For feedback about user finishing usage of the editor, the host application should use onEditorFinishCallback option callback passed during wrapper instantiation. The function passed to this parameter would be then called by the editor upon when the user finishes his work. The function will also retrieve projectId as its argument, which host application should store to be associated with a created order item. In order to close iframe close() method should be called.

Depending on the underlying logic of the host application upon handling this callback, it should either allow further configuration of the product, or just redirect to the cart.

Editor Wrapper : see Editor Wrapper. Editor Wrapper methods : see Editor wrapper methods. Editor Wrapper options : see Editor wrapper options.

Editing of existing user project

Now we will follow the scenario in which the customer wants to edit his project once again before finishing the order. We assume that the project is already generated and associated with the customer order item present in the cart.

Steps for performing this scenario may look like this :

1. Start user work session

On the server-side (usually in the product configuration action of the controller), the host application should use WEBAPI and call the work session start method and request a user mode work session (passing the userId and projectId obtained during the initial project creation). Received session token should be then passed to the rendering of the view.

Work Session : see Work Sessions Access to WEBAPI : see API credentials WEBAPI authentication : see WEBAPI Post request Starting Work Session : see Work session – start new editor session

2. Open editor with editor wrapper

After obtaining work session token, host application can now render the view using the editor wrapper. In order to do so, view should include editor wrapper library, create proper editor container and run wrapper code (passing obtained session token to it). Editor will then embed its iframe into that container.

For feedback about user finishing usage of the editor, the host application should use onEditorFinishCallback option callback passed during wrapper instantiation.

Depending on the underlying logic of the host application upon handling this callback, it should either allow further configuration of the product, or just redirect back to the cart.

Editor Wrapper : see Editor Wrapper Editor Wrapper methods : see Editor wrapper methods Editor Wrapper options : see Editor wrapper options

Downloading PDF file of project

In this scenario we assume that user project is already generated and its projectId is stored somewhere in the host application. We want to download generated PDF file and store it in host application.

1. Generate download URL

In order to download project PDF, the host application should call WEBAPI to generate a download URL. Resulting URL will be random and available to anyone who knows it for 20 minutes after generation. When time expires, the download will be no longer available and a new URL should be generated.

2. Providing access to project

In order to pass the file to the user, the host application could follow one of these scenarios: - pass generated URL directly to the user - stream binary file through its own action in the controller - download the binary file to server and treat it as its own resource

Opening user editor iframe with product gateway

Although Editor could perfectly work with existing product configurator app, it could also configure and show pricing of the product on its own, directly on editor iframe. In order to achieve this, the host application has to implement the Product gateway callback API (for more information see: Product Gateway).

Steps for performing this scenario may look like this:

1. Editor user creation

All user work sessions have to work in context of a single, selected user that has to be created using the WEBAPI. This limitation prevents users from seeing content made by other users.

In general usage scenarios, the host application has its own customer entity. Before any of the customers could access the editor, the host system has to create individual user records for them thorough the WEB API. We recommend to generate userId upon first customer editor usage and then store it in customer record for future usage.

When host application does not implement customer entity (for example it provides service to anonymous users) it could store userId in session, or even generate new userId for each editor usage, but re usage of user-created content maybe then not possible.

Work Session : see Work Sessions Access to WEBAPI : see API credentials WEBAPI authentication : see WEBAPI Post request Adding user : see Users – add user

2. Start user work session

When user is already created and host application has its userId, work session could be started. On the server-side (usually in the product configuration action of the controller), the host application should use WEBAPI and call the work session start method and request a user mode work session with: - userId received in previous step - product gateway config

Configuration of product gateway consists basically of product identifier (a string unique to a product) and URLs that lead to implemented Product Gateway callback API For more information see Product Gateway paragraph.

Product gateway : see Product gateway Work Session : see Work Sessions Access to WEBAPI : see API credentials WEBAPI authentication : see WEBAPI Post request Starting Work Session : see Work session – start new editor session

3. Open editor with editor wrapper

After obtaining work session token, host application can now render the view using the editor wrapper. In order to do so, view should include editor wrapper library, create proper editor container and run wrapper code (passing obtained session token to it). Editor will then embed its iframe into that container.

It is assumed that the host application has already implemented the underlying JavaScript application that is used for product configuration. Editor wrapper code is a single class written in pure JavaScript that could be easily integrated with any tech-stack. The editor will open its iframe directly after the instantiation of this class and then calling method open().

When product gateway is properly configured for a used work session, the host application could use onProductUpdateCallback editor wrapper callback. The passed function will be called with each product setup change with the current setup in the argument. Underlying logic could then update its own settings to preserve the consistency of configuration.

For feedback about user finishing usage of the editor, the host application should use onEditorFinishCallback option callback passed during wrapper instantiation. The function passed to this parameter would be then called by the editor upon when the user finishes his work. The function will also retrieve projectId as its argument, which host application should store to be associated with a created order item. In order to close iframe close() method should be called.

Depending on the underlying logic of the host application upon handling this callback, it should either allow further configuration of the product, or just redirect to the cart.

Product gateway : see Product Gateway Editor Wrapper : see Editor Wrapper Editor Wrapper methods : see Editor wrapper methods Editor Wrapper options : see Editor wrapper options

WEBAPI Reference

WEBAPI is API using HTTP POST and GET request methods. It is used to manage editor setup and creation of Editor work sessions.

API Credentials

When merchant gains access to the Editor resources, he receives three parameters, required to use the WEBAPI :

WEBAPI URL

This parameter defines the domain of WEBAPI, which should be used. Each API call (described in further paragraphs) should begin with this URL.

WEBAPI Key

This parameter is used for Merchant identification.

WEBAPI Secret

This parameter is used to sign each API call. Further details are described in the next paragraph.

Role of WEBAPI key and secret

WEBAPI uses a symmetric security scheme with the signing of each request. The API key and secret are random strings safely generated during the creation of a merchant. API Key is public identification of the merchant and is explicitly set in the header of each request. A secret is used to generate request authentication signs and should never be shown or sent explicitly. Both of them will be provided to the third party systems thorough safe external channels.

WEBAPI GET requests

All GET requests to WEBAPI should contain headers as described below:

Header name Contents
api-key Plain api key
api-sign Request sign generated upon each call. Its generation algorithm is described in section Request Sign generation. The server will deny access if provided request sign is not valid.

GET request sign generation

Request sign is generated using this algorithm: 1) Hash API secret key using SHA256 algorithm 2) Hash ‘GET’ string with an HMAC-SHA256 function using hashed (in previous step) API secret key

Examples

PHP sign generation:

$secretKey = 'SomeRandomSecretKeyString';
$stringToHash = ‘GET’ ;
$hashedSecret = hash('sha256', $secretKey) ;
$requestSign = hash_hmac("sha256", $stringToHash, $hashedSecret);

NodeJs sign generation:

const CryptoJS = require("crypto-js");
lety stringToHash = ‘GET’;
let requestSign = CryptoJS.HmacSHA256(
     stringToHash,
     CryptoJS.SHA256(secret).toString()
).toString();

WEBAPI POST requests

All POST requests to WEBAPI should contain data in JSON format (object with fields defined by the method) in its body and headers as described below:

Header name Contents
Content-Type application/json
api-key Plain api key
api-sign Request sign generated upon each call. Its generation algorithm is described in section Request Sign generation. The server will deny access if provided request sign is not valid.

POST request sign generation

Request sign is generated using this algorithm: 1) Store raw request body as a string 2) Hash API secret key using SHA256 algorithm 3) Hash stored raw request body with an HMAC-SHA256 function using hashed (in previous step) API secret key

Examples

PHP sign generation:

$jsonBody = '{"some-example-json-data":"example-value"}';
$secretKey = 'SomeRandomSecretKeyString';
$stringToHash = $jsonBody;
$hashedSecret = hash('sha256', $secretKey) ;
$requestSign = hash_hmac("sha256", $stringToHash, $hashedSecret);

NodeJs sign generation:

const CryptoJS = require("crypto-js");
let jsonBody = '{"some-example-json-data":"example-value"}';

lety stringToHash = jsonBody;

let requestSign = CryptoJS.HmacSHA256(
    stringToHash,
    CryptoJS.SHA256(secret).toString()
).toString();

API response structure

All WEBAPI methods responses are in JSON format with structure as seen below :

{
    "success": true,
    "data": {
        ...data specific to called method...
    },
    "error": "Some error description"
}
Field Description Data type
success Indicates if API call was successful Boolean
data (optional) Object with method data (this field shows only if success is set true) Object
details (optional) Error message (this field shows only if success is set false) String

Please note, that field success represents if server encounters any errors during the execution (either by wrong call parameters, or by internal server error).

API result pagination

Some API method results (for example user list) may return paginated results. All responses from these methods would fall into a structure as shown below :

{
    "success": true,
    "data": {
        "entities": [
            ...queried entities...
        ],
        "limit": 30,
        "offset": 0,
        "total": 3
    }
}

Paginated results data object will always contain fields listed in table below : Field | Description | Data type --------|-------------|----------- entities|Array of objects queried by method (for example users)|Array limit |Maximum number of objects on per page|Integer offset |Offset of first element of current page (starting from 0).|Integer total |Total number of all records for this method|Integer

Pagination works in a similar way to SQL limit and offset parameters. By passing limit parameter, we define page size. By passing offset parameter we define number of the first element to show on queried page (in normal use case offset should be incremented by limit value for each next page, until it hit total value).

All WEBAPI methods implementing pagination are GET methods, so both limit and offset parameters should be passed in query string (GET parameters).

API methods

Server side configuration and interaction with Editor is achieved by using method listed below. All calls must contain security headers described in API GET requests and API POST requests.

Users – get list

This action provides list of all users (and their basic data) registered for merchant. Result of this method is paginated. - | - ----|----------------------------------- URL | <WEBAPI URL> /api/v1/user/list Method|GET Parameters|• limit (integer) – page size
• offset (integer) – pagination offset Response format|JSON

Response structure Field | Description | Data type ------|-------------|---------- success|Indicates if API call was successful|Boolean data (optional)|Array of paginated User objects (this field shows only if success is set true)|Object details (optional)|Error message (this field shows only if success is set false)|String

Sample JSON response: Example 1:

{
    "success": true,
    "data": {
        "entities": [
            {
                "id": "05a9610f-52ff-11ea-8594-0242ac150002",
                "username": "John Doe",
                "email": "john.doe@key2print.com"
            },
            {
                "id": "2827d57e-7a3f-11ea-94a2-0242ac120004",
                "username": "Jane Doe",
                "email": "jane.doe@key2print.com"
            },
            {
                "id": "2aa72675-7a3f-11ea-94a2-0242ac120004",
                "username": "John Public",
                "email": "john.public@key2print.com"
            }
        ],
        "limit": 30,
        "offset": 0,
        "total": 3
    }
}

Users - add user

This method allows the adding of the new users to the system. - | - ----|----------------------------------- URL | <WEBAPI URL> /api/v1/user/add Method|POST Parameters|• none Response format|JSON

Request body structure Field | Required | Description | Data type ------|----------|-------------|---------- username|Yes|Username of created user|String email|Yes|Email of created user|String

Sample JSON request: Example 1:

{
    "username": "John Q. Public",
    "email": "jpublic@key2print.com"
}

Response structure Field | Description | Data type ------|-------------|----------- success|Indicates if API call was successful|Boolean data (optional)|User object (this field shows only if success is set true)|Object error_message (optional)|Error message (this field shows only if success is set false)|String

Sample JSON response: Example 1:

{
    "success": true,
    "data": {
        "id": "f80251af-8eb0-11ea-ba23-0242ac120003",
        "username": "John Q. Public",
        "email": "jpublic@key2print.com"
    }
}

Users – update user

This method allows the updating of the existing user's data. - | - ----|----------------------------------- URL | <WEBAPI URL> /api/v1/user/update Method|POST Parameters|• none Response format|JSON

Request body structure Field | Required | Description | Data type --------|----------|-------------|---------- id |Yes|Id of user to update|String (UUID) username|No|New username of updated user|String email |No|New email of updated user|String

Sample JSON request: Example 1:

{
    "id": "f80251af-8eb0-11ea-ba23-0242ac120003",
    "username": "Jane Q. Public"
}

Response structure Field | Description | Data type ------|-------------|------------ success|Indicates if API call was successful|Boolean data (optional)|User object (this field shows only if success is set true)|Object error_message (optional)|Error message (this field shows only if success is set false)|String

Sample JSON response: Example 1:

{
    "success": true,
    "data": {
        "id": "f80251af-8eb0-11ea-ba23-0242ac120003",
        "username": "Jane Q. Public",
        "email": "jpublic@key2print.com"
    }
}

Users – remove user

This method removing of existing user data. - | - ----|----------------------------------- URL | <WEBAPI URL> /api/v1/user/remove Method|POST Parameters|• none Response format|JSON

Request body structure Field | Required | Description | Data type --------|----------|----------------------|---------- id | Yes | Id of user to remove | String (UUID)

Sample JSON request: Example 1:

{
 "id": "f80251af-8eb0-11ea-ba23-0242ac120003"
}

Response structure Field | Description | Data type ------|-------------|------------ success|Indicates if API call was successful|Boolean data (optional)|Empty object|Object error_message (optional)|Error message (this field shows only if success is set false)|String

Sample JSON response: Example 1:

{
    "success": true,
    "data": {
    }
}

Template formats – get list

This action provides list of all template formats (and their basic data) created by merchant. Result of this method is paginated. - | - ----|----------------------------------- URL | <WEBAPI URL> /api/v1/template_format/list Method|GET Parameters|• limit (integer) – page size
offset (integer) – pagination offset
pageWidth (integer) – optional page width filter
pageHeight (integer) – optional page height filter Response format|JSON

Response structure Field | Description | Data type ------|-------------|------------ success|Indicates if API call was successful|Boolean data (optional)|Array of paginated Template format objects (this field shows only if success is set true)|Object details (optional)|Error message (this field shows only if success is set false)|String

Sample JSON response: Example 1:

{
"success": true,
"data": {
    "entities": [
        {
            "id": "09ac3b38-7b21-11ea-b993-0242ac120002",
            "name": "Page A4",
            "pageWidth": 210,
            "pageHeight": 297,
            "pageBleed": 5,
            "isDefault": true,
            "projects": []
        },
        {
            "id": "25bc649e-3b9e-11ea-96ae-0242ac120003",
            "name": "Page A5",
            "pageWidth": 148,
            "pageHeight": 210,
            "pageBleed": 5,
            "isDefault": false,
            "projects": [
                {
                    "id": "005c73f7-6dc4-11ea-a407-0242ac1d0005",
                    "name": "Flyer template 1",
                    "description": "Lorem ipsum dolor sit amet",
                    "thumbnailUrl": "https://via.placeholder.com/400x400?
text=400x400",
                    "thumbnailWidth": 400,
                    "thumbnailHeight": 400
                },
                {
                    "id": "151da362-6dc4-11ea-a407-0242ac1d0005",
                    "name": "Flyer template 2",
                    "description": "Lorem ipsum dolor sit amet",
                    "thumbnailUrl": "https://via.placeholder.com/400x400?
text=400x400",
                    "thumbnailWidth": 400,
                     "thumbnailHeight": 400
                },
                {
                    "id": "199ad097-3eaa-11ea-be1d-0242ac120002",
                    "name": "Flyer template 3",
                    "description": "Lorem ipsum dolor sit amet",
                    "thumbnailUrl": "https://via.placeholder.com/400x400?
text=400x400",
                    "thumbnailWidth": 400,
                    "thumbnailHeight": 400
                }
            ]
        }
    ],
    "limit": 30,
    "offset": 0,
    "total": 2
    }
}

Template formats – add template format

This method allows the adding of the new template formats to the system. - | - ----|----------------------------------- URL | <WEBAPI URL> /api/v1/template_format/add Method|POST Parameters|• none Response format|JSON

Request body structure Field |Required | Description | Data type ------|---------|-------------|------------ name | Yes | Name of created template format | String description | No | Description of created template format | String pageWidth | Yes | Page width in millimeters | Integer pageHeight | Yes | Page height in millimeters | Integer pageBleed | Yes | Page bleed in millimeters | Integer markAsDefault | No | Marks template format as default (if true, also disables current default template format) | Boolean

Sample JSON request: Example 1:

{
    "name": "Page A3",
    "description": "Lorem ipsum dolor sit amet",
    "pageWidth": 297,
    "pageHeight": 420,
    "pageBleed": 5,
    "markAsDefault": false
}

Response structure Field | Description | Data type ------|-------------|----------- success | Indicates if api call was successful | Boolean data (optional) | Template format object (this field shows only if success is set true) | Object error_message (optional) | Error message (this field shows only if success is set false) | String

Sample JSON request: Example 1:

{
    "success": true,
    "data": {
        "id": "b6233983-8eb8-11ea-ba23-0242ac120003",
        "name": "Page A3",
        "description": "Lorem ipsum dolor sit amet",
        "pageWidth": 297,
        "pageHeight": 420,
        "pageBleed": 5,
        "markAsDefault": false,
        "projects": []
    }
}

Template formats – update template format

This method allows the updating of the existing template format data. - | - ----|----------------------------------- URL | <WEBAPI URL> /api/v1/template_format/update Method|POST Parameters|• none Response format|JSON

Request body structure Field |Required | Description | Data type ------|---------|-------------|------------ id | Yes | Id of template format to update | String (UUID) name | No | Name of created template format | String description | No | Description of created template format | String pageWidth | No | Page width in millimeters | Integer pageHeight | No | Page height in millimeters | Integer pageBleed | No | Page bleed in millimeters | Integer markAsDefault | No | Marks template format as default (if true, also disables current default template format) | Boolean

Sample JSON request: Example 1:

{
    "id": "b6233983-8eb8-11ea-ba23-0242ac120003",
    "markAsDefault": true
}

Response structure Field | Description | Data type ------|-------------|----------- success | Indicates if API call was successful | Boolean data (optional) | Template format object (this field shows only if success is set true) | Object error_message (optional) | Error message (this field shows only if success is set false) | String

Sample JSON response: Example 1:

{
    "success": true,
    "data": {
        "id": "b6233983-8eb8-11ea-ba23-0242ac120003",
        "name": "Page A3",
        "description": "Lorem ipsum dolor sit amet",
        "pageWidth": 297,
        "pageHeight": 420,
        "pageBleed": 5,
        "markAsDefault":true,
        "projects": []
    }
}

Template formats – remove template format

This method allows removing of existing template format. - | - ----|----------------------------------- URL | <WEBAPI URL> /api/v1/template_format/remove Method|POST Parameters|• none Response format|JSON

Request body structure Field |Required | Description | Data type ------|---------|-------------|------------ id | Yes | Id of template format to remove | String (UUID)

Sample JSON request: Example 1:

{
    "id": "b6233983-8eb8-11ea-ba23-0242ac120003"
}

Response structure Field | Description | Data type ------|-------------|----------- success | Indicates if API call was successful | Boolean data (optional) | Empty object | Object error_message (optional) | Error message (this field shows only if success is set false) | String

Sample JSON response: Example 1:

{
    "success": true,
    "data": {
    }
}

Projects – get list

This action provides list of all projects (created by selected user) or project templates (created by merchant). Result of this method is paginated.

- -
URL <WEBAPI URL> /api/v1/project/list
Method GET
Parameters limit (integer) – page size
offset (integer) – pagination offset
templateFormatId (integer) – optional template format filter
userId (integer) – optional userId (if omitted, method will return project templates)
Response format JSON

Response structure Field | Description | Data type ------|-------------|----------- success | Indicates if API call was successful | Boolean data (optional) | Array of paginated Project objects (this field shows only if success is set true) | Object details (optional) | Error message (this field shows only if success is set false) | String

Sample JSON response: Example 1:

{
    "success": true,
    "data": {
        "entities": [{
                "id": "199ad097-3eaa-11ea-be1d-0242ac120002",
                "name": "First project",
                "description": "Lorem ipsum dolor sit amet",
                "isPublished": false,
                "templateFormat": {
                    "id": "b6233983-8eb8-11ea-ba23-0242ac120003",
                    "name": "Page A3",
                    "pageWidth": 297,
                    "pageHeight": 420,
                    "pageBleed": 5,
                    "isDefault": false
                },
                "pages": [],
                "setup": []
            },
            {
                "id": "50b4e16d-3eaa-11ea-be1d-0242ac120002",
                "name": "Second project",
                "description": "Lorem ipsum dolor sit amet",
                "isPublished": false,
                "templateFormat": {
                    "id": "b6233983-8eb8-11ea-ba23-0242ac120003",
                    "name": "Page A3",
                    "pageWidth": 297,
                    "pageHeight": 420,
                    "pageBleed": 5,
                    "isDefault": false
                },
                "pages": [],
                "setup": []
            }
        ],
        "limit": 30,
        "offset": 0,
        "total": 2
    }
}

Placeholders – get list

This action provides list of all placeholders (and their basic data) created by merchant. Result of this method is paginated. - | - ----|----------------------------------- URL | <WEBAPI URL> /api/v1/placeholder/list Method|GET Parameters| • limit (integer) – page size
offset (integer) – pagination offset Response format|JSON

Response structure Field | Description | Data type ------|-------------|----------- success | Indicates if API call was successful | Boolean data (optional) | Array of paginated Placeholder objects (this field shows only if success is set true) | Object details (optional) | Error message (this field shows only if success is set false) | String

Sample JSON response: Example 1:

{
    "success": true,
    "data": {
        "entities": [{
                "id": "35d2d5df-a64b-11ea-a5e2-0242ac140002",
                "name": "Your company name",
                "systemName": "company_name",
                "type": "text",
                "acceptedParameters": [
                    "value"
                ]
            },
            {
                "id": "66a34412-a65b-11ea-a5e2-0242ac140002",
                "name": "Phone number",
                "systemName": "phone",
                "type": "text",
                "acceptedParameters": [
                    "value"
                ]
            }
        ],
        "limit": 30,
        "offset": 0,
        "total": 2
    }
}

Placeholders – add placeholder

This method allows the adding of the new placeholder to the system. - | - ----|----------------------------------- URL | <WEBAPI URL> /api/v1/placeholder/add Method|POST Parameters| • none Response format|JSON

Request body structure Field | Required | Description | Data type ------|----------|-------------|----------- name | Yes| Name of created placeholder | String systemName | Yes | Unique system name used during data insertion to the user work session (system name is never visible to the user) | String type | Yes | Type of field (text) | String

Sample JSON request: Example 1:

{
    "name": "Your company name",
    "systemName": "company_name",
    "type": "text"
}

Response structure Field | Description | Data type ------|-------------|------------ success | Indicates if api call was successfull | Boolean data (optional) | Placeholder object (this field shows only if success is set true) | Object error_message (optional) | Error message (this field shows only if success is set false) | String

Sample JSON response: Example 1:

{
    "success": true,
    "data": {
        "id": "35d2d5df-a64b-11ea-a5e2-0242ac140002",
        "name": "Your company name",
        "systemName": "company_name",
        "type": "text",
        "acceptedParameters": [
            "value"
        ]
    }
}

Placeholders – update placeholder

This method allows the updating of the existing placeholder data. - | - ----|----------------------------------- URL | <WEBAPI URL> /api/v1/placeholder/update Method|POST Parameters| • none Response format|JSON

Request body structure Field | Required | Description | Data type ------|----------|-------------|----------- id | Yes | Id of placeholder to update | String (UUID) name | No | Name of created placeholder | String systemName | No | Unique system name used during data insertion to the user work session (system name is never visible to the user) | String type | No | Type of field (text) | String

Sample JSON request: Example 1:

{
    "id": "35d2d5df-a64b-11ea-a5e2-0242ac140002",
    "name": "This is company name"
}

Response structure Field | Description | Data type ------|-------------|------------ success | Indicates if API call was successful | Boolean data (optional) | Placeholder object (this field shows only if success is set true) | Object error_message (optional) | Error message (this field shows only if success is set false) | String

Sample JSON response: Example 1:

{
    "success": true,
    "data": {
        "id": "35d2d5df-a64b-11ea-a5e2-0242ac140002",
        "name": "This is company name",
        "systemName": "company_name",
        "type": "text",
        "acceptedParameters": [
            "value"
        ]
    }
}

Placeholders – remove placeholder

This method allows removing of existing placeholder. - | - ----|----------------------------------- URL | <WEBAPI URL> /api/v1/placeholder/remove Method|POST Parameters| • none Response format|JSON

Request body structure Field | Required | Description | Data type ------|----------|-------------|----------- id | Yes | Id of placeholder to remove | String (UUID)

Sample JSON request: Example 1:

{
    "id": "35d2d5df-a64b-11ea-a5e2-0242ac140002"
}

Response structure Field | Description | Data type ------|-------------|------------ success | Indicates if API call was successful | Boolean data (optional) | Empty object | Object error_message (optional) | Error message (this field shows only if success is set false) | String

Sample JSON response: Example 1:

{
    "success": true,
    "data": {}
}

Work session – start new editor session

This method allows the creation of work sessions that represents the context of the opened editor frame. For more information see the Work Sessions paragraph. - | - ----|----------------------------------- URL | <WEBAPI URL> /api/v1/session/start Method|POST Parameters| • none Response format|JSON

Request body structure Field | Required | Description | Data type ------|----------|-------------|----------- mode | Yes | Work session mode. There are two available work session modes: merchant and user | String userId | Yes | Id of user for user work session. This field should be omitted when starting merchant mode. | String (UUID) projectId | No | Id of project for user work session. If this was not specified, new system with start session with new blank project. This field should be omitted when starting merchant mode. | String (UUID) projectTemplateId | No | Id of project template which contents should be copied to newly created user project. | String (UUID) productGatewaySetup | No | Optional setup of product gateway | Object editorSetup | No | Optional setup of editor | Object placeholderValues | No | Optional placeholders values | Object

Product gateway setup:

"productGatewaySetup": {
    "productIdentifier": "Product identifier",
    "productDetailsUrl": "Get Product Data URL",
    "availableOptionsUrl": "Get Available Options URL",
    "priceUrl": "GET Price URL",
    "setupDataUrl": "GET Editor values URL"
}

Product gateway is available only for the user mode. For more information see Product Gateway Reference.

Editor setup

"editorSetup": {
    "colors": {
        "primaryColor": “310048” //hex format
    },
    "hiddenTabs": {
        "themeTab": true / false,
        "imageTab": true / false,
        "photoCellTab": true / false,
        "textTab": true / false,
        "shapeTab": true / false,
        "placeholderTab": true / false
    }
}

Option “hiddenTabs” is available only for the user mode. Option “colors” could be applied for both user and merchant modes.

Placeholder values:

"placeholderValues": {
    "placeholderSystemName": {
        "placeholderParameterName": “placeholderParameterContent”
    }
}

Placeholder values are available only in the user mode.

Sample JSON request: Example 1:

{
"mode": "merchant"
}

Example 2:

{
    "mode": "user",
    "userId": "f80251af-8eb0-11ea-ba23-0242ac120003"
}

Example 3:

{
    "mode": "user",
    "userId": "f80251af-8eb0-11ea-ba23-0242ac120003",
    "placeholderValues": {
        "company_name": {
            "value": "Key2print"
        }
    }
}

Example 4:

{
    "mode": "user",
    "userId": "f80251af-8eb0-11ea-ba23-0242ac120003",
    "editorSetup": {
        "colors": {
            "primaryColor": “310048”
        },
        "hiddenTabs": {
            "themeTab": true,
            "imageTab": false,
            "photoCellTab": false,
            "textTab": false,
            "shapeTab": false,
            "placeholderTab": false
        }
    }
}

Response structure Field | Description | Data type ------|-------------|------------ success | Indicates if API call was successful | Boolean data (optional) | Work session object (this field shows only if success is set true) | Object error_message (optional) | Error message (this field shows only if success is set false) | String

Sample JSON response: Example 1:

{
    "success": true,
    "data": {
        "id": "283d87e1-8ec4-11ea-ba23-0242ac120003",
        "hash": "JDJ5JDEwJGcxT0d2cHFOamRabnZsOHVCWU41bU9RUmRodTIvRGZVN3BaQmdtVkZSSVRQaVlTN1lEOVUy",
        "mode": "merchant",
        "merchant": {
            "id": "271246b6-3854-11ea-bcf7-0242ac120003",
            "name": "Example Merchant"
        },
        "user": null,
        "editorSetup": {
            "colors": {
                "primaryColor": “310048”
            }
        },
        "createdAt": "2020-05-05 11:32:52",
        "expiresAt": "2020-05-05 12:32:52",
        "hasExpired": false
    }
}

Example 2:

{
    "success": true,
    "data": {
        "id": "4801ccf4-8ec4-11ea-ba23-0242ac120003",
        "token": "JDJ5JDEwJDBZRHF3MkZkcFNkQkk5Z3AzSHdwMmVuTjUzTkFyb29XNEtJczF6YmdwUDdQUkVxcUgwaWRh",
        "mode": "user",
        "merchant": {
            "id": "271246b6-3854-11ea-bcf7-0242ac120003",
            "name": "Example Merchant"
        },
        "user": {
            "id": "f80251af-8eb0-11ea-ba23-0242ac120003",
            "username": "John Q. Public"
        },
        "productGatewayEnabled": false,
        "editorSetup": {
            "colors": {
                "primaryColor": “310048”
            },
            "hiddenTabs": {
                "themeTab": false,
                "imageTab": false,
                "photoCellTab": false,
                "textTab": false,
                "shapeTab": false,
                "placeholderTab": false
            }
        },
        "createdAt": "2020-03-05 11:33:46",
        "expiresAt": "2020-03-05 12:33:46",
        "hasExpired": false,
        "project": {
            "id": "4803155d-8ec4-11ea-ba23-0242ac120003",
            "name": "New project",
            "templateFormat": {
                "id": "b6233983-8eb8-11ea-ba23-0242ac120003",
                "name": "Page A3",
                "pageWidth": 297,
                "pageHeight": 420,
                "pageBleed": 5,
                "isDefault": true
            },
            "user": {
                "id": "f80251af-8eb0-11ea-ba23-0242ac120003",
                "username": "John Q. Public"
            }
        }
    }
}

Project – download

This action allows the generation of download links to finished projects. Each of the links will expire 20 minutes after generation.

- -
URL <WEBAPI URL> /api/v1/project/download/{id}
Method GET
Parameters id (string UUID) – project UUID
Response format JSON

Response structure Field | Description | Data type ------|-------------|------------- success | Indicates if API call was successful | Boolean data (optional) | Object with download link | Object details (optional) | Error message (this field shows only if success is set false) | String

Sample JSON response: Example 1:

{
    "success": true,
    "data": {
        "download_url": "https://key2print.s3.eu-west-.amazonaws.com/271246b6385411eabcf70242ac120003%2F8777fasd8a52f4d95fa7ec3d1610144"
    }
}

Product gateway – error log

This action provides list of all errors that occurred during the product gateway calls. Result of this method is paginated. - | - ----|----------------------------------- URL | <WEBAPI URL> /api/v1/error_log/list Method|GET Parameters| • limit (integer) – page size
offset (integer) – pagination offset
tstampFrom (integer) – optional unix timestamp from
tstampTo (integer) – optional unix timestap to
productIdentifier (string) – optional product identifier Response format|JSON

Response structure Field | Description | Data type ------|-------------|------------- success | Indicates if API call was successful | Boolean data (optional) | Array of paginated Error log objects (this field shows only if success is set true)| Object details (optional) | Error message (this field shows only if success is set false) | String

Sample JSON response: Example 1:

{
    "success": true,
    "data": {
        "entities": [{
                "details": "Product not found",
                "tstamp": 1588376400,
                "date": "2020-05-01 23:40:00",
                "productIdentifier": 5,
                "method": "getProductDetails"
            },
            {
                "details": "Product not found",
                "tstamp": 1588376350,
                "date": "2020-05-01 23:39:10",
                "productIdentifier": 5,
                "method": "getProductData"
            }
        ],
        "limit": 30,
        "offset": 0,
        "total": 2
    }
}

Product gateway – cache flush

This method allows to clear product gateway cache for selected product identifier. - | - ----|----------------------------------- URL | <WEBAPI URL> /api/v1/cache/flush Method|POST Parameters| • none Response format|JSON

Request body structure Field | Required | Description | Data type ------|----------|-------------|------------- productIdentifier | Yes | Product identifier of product cache to flush | String

Sample JSON request: Example 1:

{
    "productIdentifier": "5"
}

Response structure Field | Description | Data type ------|-------------|------------- success | Indicates if API call was successful | Boolean data (optional) | Empty object | Object error_message (optional) | Error message (this field shows only if success is set false) | String

Sample JSON response: Example 1:

{
    "success": true,
    "data": {}
}

Editor Wrapper

Editor Wrapper is a small library which facilitates the process of opening editor iframe for a created work session (see starting work session). Its codebase is written in pure JavaScript to prevent any conflicts with an underlying host Host application.

Wrapper usage

This simple example code snippet could be inserted into desired application view:

<script type="text/javascript" src="https://k2p-editor-test.s3-eu-west1.amazonaws.com/js/wrapper.js"></script>
<div id="editor_container"></div>

<script>
    (function () {
        let wrapper = new K2PEditorWrapper("editor_container", {
            sessionToken:'JDJ5JDEwJDBZRHF3MkZkcFNkQkk5Z3AzSHdwMmVuTjUzTkFy
b29XNEtJczF6YmdwUDdQUkVxcUgwaWRh',
            onEditorFinishCallback: function (projectId) {
                alert('Editor finished successfully: '+projectId);
            },
            onProductUpdateCallback: function (productData) {
                alert('Editor updated product setup');
                console.log(productData);
            }
        });
        wrapper.open();
    })()'
</script>

In this basic usage example, there are five things that took place: 1. Editor wrapper library is loaded into page using standard script tag, with ‘src’ attribute.

<script type="text/javascript" src="https://k2p-editor-test.s3-eu-west1.amazonaws.com/js/wrapper.js"></script>
  1. Place where iframe should be inserted is declared by creating a container with a specified ID attribute. This ID should be passed to the loader class in the next step. All contents of the container would be replaced with iframe.
<div id="editor_container"></div>
  1. K2pEditorWrapper gets instantiated with two arguments:
  2. container ID string
  3. editor wrapper options JSON (see options reference)

Session Token (prior generated by WEBAPI – see starting work session) is passed as sessionToken option field.

Fields onEditorFinishCallback and onProductUpdateCallback expects callback functions, which would be called on certain events that took place inside of editor application (see options reference). These functions are points, where Host application could interact with Editor frontend running in iframe. For example, when Editor calls onEditorFinishCallback Host application could store projectId in database and add product to cart.

let wrapper = new K2PEditorWrapper("editor_container", {
    sessionToken: 'JDJ5JDEwJDBZRHF3MkZkcFNkQkk5Z3AzSHdwMmVuTjUzTkFy
    b29XNEtJczF6YmdwUDdQUkVxcUgwaWRh ',
    width: '100%',
    height: '1000px',
    onEditorFinishCallback: function(projectId) {
        alert('Editor finished successfully: ' + projectId);
    },
    onProductUpdateCallback: function(productData) {
        alert('Editor updated product setup');
        console.log(productData);
    }
});
  1. When everything is set, the Host application could open editor iframe by calling open() function.
wrapper.open();

Wrapper Method Reference

K2PEditorWrapper(editorContainerId, options); Wrapper constructor. Argument | Description | Data type ---------|-------------|--------------- editorContainerId | ID attribute of container to open editor iframe. Please note that it has to be an ID attribute, not the class. | String options | Options object (see options reference) | Object


open(); Returns void. This method opens Editor iframe. Argument | Description | Data type ---------|-------------|--------------- none|none|none


close(); Returns void. This method closes Editor iframe. Argument | Description | Data type ---------|-------------|--------------- none|none|none

Wrapper Option Reference

These options are passed in contructor of K2PEditorWrapper. Field | Description | Data type ------|-------------|------------- sessionToken | Session token generated via WEBAPI (see starting work session). It is required to authenticate Editor Frontend context. | String onEditorFinishCallback | Passed function would be called upon editor finish (triggered from Editor Frontend). It receives string with projectId as argument. | Function onProductUpdateCallback | Passed function would be called upon product parameter change in editor window. This method is called only when Product Gateway was configured for the Work session. It receives object with Product Setup as argument. (see Product Gateway for more information) | Function width | Optional Iframe width attribute. Defaults to 1024px. It accepts standard css units like pixels, percents, etc. | String height | Optional Iframe height attribute. It accepts standard css units like pixels, percents, etc. Defaults to 768px. | String

Product Gateway Reference

Product gateway is an optional editor subsystem that enables editor frontend to configure host application products while presenting their prices and additional information. Product gateway gives also the ability to map product setup to some editor parameters such as matching template format and number of pages in project.

These functionalities are achieved by implementing four API methods on the host application side that would be called by editor backend during the editor and then, passing their URLs during creation user work session. These URLs have effect only on this one work session, so it is possible to use their query string parameters to provide more information to callback methods (for example selected user language in case of multilingual host applications).

Callback API description

There are four methods of callback API that has to be implemented:

Get Product Details – method to provide basic information about the product like name, options list, and default product setup.

Get Available Options – method to provide information which combinations of options are available to order (we assume that available setups may not be just the Cartesian product of option values)

Get Price – method to provide price and some additional info data of selected setup. Data provided for this method could also have a form of a multidimensional array to support additional parameters like tax rate, or delivery method.

Get Setup Data – method to map product setup to particular editor settings like canvas size (by matching template format) or a number of pages.

General work principle

General work principle and sequence of API calls could be described by these points: 1. The editor loads it window and checks if requested work session has configured product gateway. If so, it renders a product configuration window and calls the first product gateway method: Get Product Details. Then it could render product setup drop-downs and select default product setup. 2. When option drop-downs are rendered, the editor takes selected options (they will match default setup during the initial run) and then call Get Available Options method, to determine which options from selects should be disabled. This mechanism is implemented to prevent the selection of impossible setups (for example to prevent selection of UV coating option, when incompatible paper material was chosen). The method is pass selected setup with each user change and should always return which options are available (not disabled) for the current product setup. 3. When impossible option values were disabled, the editor calls Get Price method which should return product price for current product setup. Upon receiving the call, editor would be able to display a valid product price. Pricing could be passed either as flat price (one product setup = one price) or as price nested tree which would lead to the rendering of additional drop-downs (with a delivery method for example). 4. When a price is fully rendered, the editor passes the current product setup (also with options from pricing tree if supplied from Get Price method) to Get Setup Data method. The last method should map product setup to a number of pages and template format. Then, editor could match project setting to product setup (for example set correct canvas size for format A4).

Product options vs price options

As described in General work principle, product setup drop-downs could be generated using two methods: 1. By options determined by Get Product Details and Get Available Options. This method is designed to be used for very large products (with millions of possible setups) that the whole pricing table could not be passed at once. 2. By options determined by pricing nested tree. All possible combinations and prices are then passed during Get Price call. This method is designed to be used with small products or to add fixed additional options for large products (such as delivery method).

Depending on host application product characteristic both methods could be used both separately or simultaneously.

Expected request method and response

Each callback method should be able to handle the GET request and query string parameters (GET parameters). All responses should have code 200 and JSON body. All methods should provide their JSON response using the basic format as shown below.

{
    "success": true,
    "data": {
        ...data specific to called method...
    },
    "error": "Some error description"
}
Field Description Data type
success Indicates if API call was successful and no errors occurred Boolean
data Object with method data (this field will only be used if success is set true) Object
details Error message (this field will be logged when success is set to false) String

Product identifier

During the start of the user work session (see starting work session) host application has to provide a product identifier in a form of a string value that should be unique per each product. This parameter has three roles on system:

  1. It is sent along any call to callback API, so host application could determine product context
  2. It is used as a filter in the product gateway error logging method (see method)
  3. It is used as a key in product gateway cache flushing (see method)

Authentication

Due to the callback nature of product gateway, the editor does not authenticate responses from API and assumes that URLs passed to user work sessions are valid.

However, it is possible for the host application to authenticate calls to determine if it was made by the editor. To do so, it should parse all the query string (GET) parameters passed to the called method. Apart from parameters specific for method and additional passed during work session start (see passing additional parameters), product gateway always adds authentication parameters as below:

Parameter Description Data type
productIdentifier Product identifier passed during work session start String
key Merchant key (same as used in WEBAPI) String
tstamp Current Unix Timestamp. Could be used for ddos protection. String
sign Sign of API call. It should be compared with calculated result String

To authenticate the call, the host application has to calculate sign and compare it with the sent one. If they are different, then the call is invalid.

To calculate the sign host application should perform these steps: 1. All the query string parameters (GET) should be read and placed into associative array. 2. Parameter ‘sign’ should removed from the array and stored in another variable 3. All left parameters should be concatenated into ‘{key}={value}’ strings and placed into another array 4. The resulting array should be sorted alphabetically in the ascending order. 5. All strings in the sorted array should concatenated into one, with ‘&’ sign between chunks. 6. Hash Merchant API secret (same as used in WEBAPI) using the SHA256 algorithm 7. Hash string from point 5 with an HMAC-SHA256 function using hashed (in the previous step) API secret key 8. Result of hashing should be the same as in ‘sign’ stored in step 2.

Passing additional parameters

Although product gateway requires the host application to provide a product identifier as a basic product context it is also possible to custom parameters to query strings of method URLs passed to work session. They will be added to the parameters sent by the product gateway itself. However there is a list of reserved parameter names, that cannot be used: - productIdentifier - key - tstamp - sign - setup

Product setup format

Product setup is always passed to the methods as JSON object with field names as option ids, and values as option value ids.

{
    "ID of first option": "ID of option value",
    "ID of second option": "ID of option value",
    ...
}

Caching

In order to reduce the network traffic and to speed up the loading times, the editor incorporates caching of host application callback responses. This approach could result in presenting stalled product data when something has changed on the host application side (for example new pricing was loaded).

To prevent this scenario WEBAPI implements a flush cache method that should be called after each such change. Its scope is limited to all calls made for a specific productIdentifier.

The usage of the flush cache method is described here.

Callback API methods

Get Product Details

This method is used to pass to the editor information about basic product details such as name and default product setup. Call parameters: Field | Description | Data type ------|-------------|----------- productIdentifier | Product identifier passed during work session starting | String key | Merchant key. Same as used in WEBAPI. | String tstamp | Timestamp of call | String sign | Sign of call, used to authentication | String

Expected method response in JSON pseudo-code:

{
    "success": true,
    "data": {
        "name": "Product name",
        "defaultSetup": {
            "ID of first option": "ID of option value",
            "ID of second option": "ID of option value",
            ...
        }
        "options": [{
                "id": "First option ID"
                "name": "First option name"
                "values": [{
                        "id": "ID of option value",
                        "name": "Option value name"
                    },
                    ...
                ],
            },
            {
                "id": "Second option ID"
                "name": "Second option name"
                "values": [{
                        "id": "ID of option value",
                        "name": "Option value name"
                    },
                    ...
                ],
            },
            ...
        ]
    }
}

Example 1:

{
    "success": true,
    "data": {
        "name": "Flyer",
        "defaultSetup": {
            "1": "1",
            "2": "4"
        },
        "options": [{
                "id": "1",
                "name": "Format",
                "values": [{
                        "id": "1",
                        "name": "A3"
                    },
                    {
                        "id": "2",
                        "name": "A4"
                    },
                    {
                        "id": "3",
                        "name": "A5"
                    }
                ]
            },
            {
                "id": "2",
                "name": "Finishing",
                "values": [{
                        "id": "4",
                        "name": "None"
                    },
                    {
                        "id": "5",
                        "name": "Gloss"
                    },
                    {
                        "id": "6",
                        "name": "UV coating"
                    }
                ]
            }
        ]
    }
}

Get Available Options

This method returns information about which option values should be available for the user for the current product setup. Call parameters: Field | Description | Data type ------|-------------|------------ productIdentifier | Product identifier passed during work session starting | String key | Merchant key. Same as used in WEBAPI. | String tstamp | Timestamp of call | String sign | Sign of call, used to authentication | String setup | Selected product setup | String (JSON)

Expected method response in JSON pseudocode:

{
    "success": true,
    "data": {
        "validSetup": {
            "ID of first option": "ID of option value",
            "ID of second option": "ID of option value",
            ...
        },
        "availableOptions: {
        "ID of first option": [
            "ID of option value available for selection",
            "ID of option value available for selection",
            ...
        ],
        "ID of second option": [
            "ID of option value available for selection",
            "ID of option value available for selection",
            ...
        ],
        ...
    }
}
}

Example 1:

{
    "success": true,
    "data": {
        "validSetup": {
            "1": "1",
            "2": "4"
        },
        "availableOptions": {
            "1": [
                "1",
                "2"
            ],
            "2": [
                "3",
                "4"
            ]
        }
    }
}

Get Price

This method returns the product setup price or additional price nested tree. Call parameters: Field | Description | Data type ------|-------------|----------- productIdentifier | Product identifier passed during work session starting | String key | Merchant key. Same as used in WEBAPI. | String tstamp | Timestamp of call | String sign | Sign of call, used to authentication | String setup | Selected product setup | String (JSON)

Expected method response in JSON pseudo-code (for single price case):

{
    "success": true,
    "data": {
        "netPrice": float with net price,
        "grossPrice": float with gross price,
        "tax": float with tax price(gross minus net),
        "taxRate": "tax rate name",
        "currency": "currency ISO code",
        "isAvailable": boolean
        if product is in stock,
        "additionalInfo": [{
                "name": "Name of additional product property",
                "value": "Value of additional product property"
            },
            ...
        ]
    }
}

Expected method multiple price response in JSON pseudo-code (for price tree with two option drop-downs):

{
    "success": true,
    "data": {
        "priceOptionTree": {
            "id": "ID of first price option",
            "name": "First price option name",
            "values": [{
                    "id": "ID of first price option value",
                    "name": "First price option name value",
                    "subOption": {
                        "id": "ID of second price option value",
                        "name": "Second price option name value",
                        "values": [{
                                "id": "ID of second price option value",
                                "name": "Second price option name value",
                                "netPrice": float with net price,
                                "grossPrice": float with gross price,
                                "tax": float with tax price(gross minus net),
                                "taxRate": "tax rate name",
                                "currency": "currency ISO code",
                                "isAvailable": boolean
                                if product is in stock,
                                "additionalInfo": [{
                                        "name": "Name of product property",
                                        "value": "Value of additional product property"
                                    },
                                    ...
                                ]
                            },
                            ...
                        ]
                    }
                },
                ...
            ]
        }
    }

Example 1 (for price tree with two option drop-downs):

{
    "success": true,
    "data": {
        "netPrice": 100.00,
        "grossPrice": 120.00,
        "tax": 20.00,
        "taxRate": "Tax 20%",
        "currency": "EUR",
        "isAvailable": true,
        "additionalInfo": [{
            "name": "Product weight",
            "value": "10 kg"
        }]
    }
}

Example 2 (for single price case):

{
    "success": true,
    "data": {
        "priceOptionTree": {
            "id": 1,
            "name": "Production time",
            "values": [{
                    "id": 1,
                    "name": "Standard",
                    "subOption": {
                        "id": 2,
                        "name": "Delivery method",
                        "values": [{
                                "id": 3,
                                "name": "Self collection",
                                "netPrice": 100.00,
                                "grossPrice": 120.00,
                                "tax": 20.00,
                                "taxRate": "Tax 20%",
                                "currency": "EUR",
                                "isAvailable": true,
                                "additionalInfo": [
                                    {
                                        "name": "Product weight",
                                        "value": "10 kg"
                                    }, {
                                        "name": "Production days",
                                        "value": "10"
                                    }
                                ]
                            },
                            {
                                "id": 4,
                                "name": "Postal delivery",
                                "netPrice": 150.00,
                                "grossPrice": 180.00,
                                "tax": 30.00,
                                "taxRate": "Tax 20%",
                                "currency": "EUR",
                                "isAvailable": true,
                                "additionalInfo": [
                                    {
                                        "name": "Product weight",
                                        "value": "10 kg"
                                    }, {
                                        "name": "Production days",
                                        "value": "10"
                                    }
                                ]
                            }
                        ]
                    }
                },
                {
                    "id": 2,
                    "name": "Express",
                    "subOption": {
                        "id": 2,
                        "name": "Delivery method",
                        "values": [
                            {
                                "id": 3,
                                "name": "Self collection",
                                "netPrice": 200.00,
                                "grossPrice": 240.00,
                                "tax": 40.00,
                                "taxRate": "Tax 20%",
                                "currency": "EUR",
                                "isAvailable": true,
                                "additionalInfo": [
                                    {
                                        "name": "Product weight",
                                        "value": "10 kg"
                                    }, {
                                        "name": "Production days",
                                        "value": "2"
                                    }
                                ]
                            },
                            {
                                "id": 4,
                                "name": "Postal delivery",
                                "netPrice": 250.00,
                                "grossPrice": 300.00,
                                "tax": 50.00,
                                "taxRate": "Tax 20%",
                                "currency": "EUR",
                                "isAvailable": true,
                                "additionalInfo": [
                                    {
                                        "name": "Product weight",
                                        "value": "10 kg"
                                    }, {
                                        "name": "Production days",
                                        "value": "2"
                                    }
                                ]
                            }
                        ]
                    }
                }
            ]
        }
    }
}

Get Setup Data

This method returns editor data matching the product setup. Call parameters:

Field Description Data type
productIdentifier Product identifier passed during work session starting String
key Merchant key. Same as used in WEBAPI. String
tstamp Timestamp of call String
sign Sign of call, used to authentication String
setup Selected product setup String (JSON)

Expected method response in JSON pseudo-code:

{
    "success": true,
    "data": {
        "pageCount": integer number of pages to edit in project,
        "templateFormatId": ID of template format matching the setup
    }
}

Example 1:

{
    "success": true,
    "data": {
        "pageCount": 11,
        "templateFormatId": "b6233983-8eb8-11ea-ba23-0242ac120003"
    }
}

A list of template formats available in the editor could be obtained as described here.